自定义函数 Partition table 分区裁剪 Partition Pruning DETERMINISTIC

SYMPTOMS

  • After upgrade to 19c, partition pruning becomes not work for the SQL with predicates of user defined function, while partition pruning works for the same SQL prior to 19c.
  • The problem can be reproduce by following test case:
     

    CREATE TABLE (
         COL1  CHAR(3)
        ,COL2  CHAR(17)
        ,COL3  NUMBER(7,0)
        ,COL4  CHAR(8)
        ,COL5  NUMBER(1,0)
    )
    PARTITION BY RANGE (COL4)
    (
        PARTITION PT_20200901 VALUES LESS THAN ('20200902'),
        PARTITION PT_20200902 VALUES LESS THAN ('20200903'),
        PARTITION PT_20200903 VALUES LESS THAN ('20200904'),
        PARTITION PT_20200904 VALUES LESS THAN ('20200905'),
        PARTITION PT_20200905 VALUES LESS THAN ('20200906'),
        PARTITION PT_20200906 VALUES LESS THAN ('20200907'),
        PARTITION PT_20200907 VALUES LESS THAN ('20200908'),
        PARTITION PT_20200908 VALUES LESS THAN ('20200909'),
        PARTITION PT_20200909 VALUES LESS THAN ('20200910'),
        PARTITION PT_20200910 VALUES LESS THAN ('20200911'),
        PARTITION PT_99999999 VALUES LESS THAN (MAXVALUE)
    );

    CREATE or REPLACE FUNCTION (ARG VARCHAR2) RETURN VARCHAR2 IS
    BEGIN
      RETURN ARG;
    END;
    /

    set lines 200
    EXPLAIN PLAN FOR SELECT * FROM WHERE COL4 <= (:B1) AND COL4 >= (:B2);
    SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());


    Test results in 19c:
     

    PLAN_TABLE_OUTPUT
    -----------------------------------------------------------------------------------------------------
    Plan hash value: 1909639130

    -----------------------------------------------------------------------------------------------------
    | Id  | Operation           | Name          | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
    -----------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT    |               |     1 |    60 |     2   (0)| 00:00:01 |       |       |
    |   1 |  PARTITION RANGE ALL|               |     1 |    60 |     2   (0)| 00:00:01 |     1 |    11 |
    |*  2 |   TABLE ACCESS FULL |   |     1 |    60 |     2   (0)| 00:00:01 |     1 |    11 | <<<<<< All partitions is being accessed
    -----------------------------------------------------------------------------------------------------

    Predicate Information (identified by operation id):

    ---------------------------------------------------

       2 - filter("COL4"<=""(:B1) AND "COL4">=""(:B2))

    Note
    -----
       - dynamic statistics used: dynamic sampling (level=2)

    18 rows selected.



    Test results prior to 19c:

     

    PLAN_TABLE_OUTPUT
    ----------------------------------------------------------------------------------------------------------
    Plan hash value: 1276201164

    ----------------------------------------------------------------------------------------------------------
    | Id  | Operation                | Name          | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
    ----------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT         |               |     1 |    60 |     2   (0)| 00:00:01 |       |       |
    |   1 |  PARTITION RANGE ITERATOR|               |     1 |    60 |     2   (0)| 00:00:01 |   KEY |   KEY |
    |*  2 |   TABLE ACCESS FULL      |   |     1 |    60 |     2   (0)| 00:00:01 |   KEY |   KEY | <<<<<< Dynamic partition pruning
    ----------------------------------------------------------------------------------------------------------

    Predicate Information (identified by operation id):

    ---------------------------------------------------

       2 - filter("COL4"<=""(:B1) AND "COL4">=""(:B2))

    Note
    -----
       - dynamic sampling used for this statement (level=2)

    18 rows selected.

CHANGES

 Upgrade to 19c.

CAUSE

This is a behavior change introduced by the fix of unpublished Bug 27175987, which is included in 19c.
The fix of unpublished Bug 27175987 is to disable partition pruning for predicates that involve non-deterministic PL/SQL functions.  

This eventually should be solved with the following internal bug:

Bug 35601787 - BULK DELETE ON LIST-HASH COMPOSITE PARITITIONED TABLE GIVES WRONG RESULT

Please also reference the following:

Document 35601787.8 - Bug 35601787 - Wrong results from partition pruning when predicate has PL/SQL functions and removal of Bug 27175987 restriction

SOLUTION

The permanent solution is to apply patch 35601787.

The following is a possible workaround to enable partition pruning:

  • Change user defined function to deterministic PL/SQL functions if it is non-deterministic, and add the DETERMINISTIC clause to the function if the function is truly deterministic:
     

    SQL> CREATE or REPLACE FUNCTION (ARG VARCHAR2) RETURN VARCHAR2 deterministic IS -- Add "deterministic"
    BEGIN
      RETURN ARG;
    END;
    /
      2    3    4    5
    Function created.

    SQL> EXPLAIN PLAN FOR SELECT * FROM   WHERE COL4 <= (:B1) AND COL4 >= (:B2);
    SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());

    Explained.

    SQL>
    PLAN_TABLE_OUTPUT
    ------------------------------------------------------------------------------------------------------------------------
    Plan hash value: 1276201164

    ----------------------------------------------------------------------------------------------------------
    | Id  | Operation                | Name          | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
    ----------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT         |               |     1 |    60 |     2   (0)| 00:00:01 |       |       |
    |   1 |  PARTITION RANGE ITERATOR|               |     1 |    60 |     2   (0)| 00:00:01 |   KEY |   KEY |
    |*  2 |   TABLE ACCESS FULL      |   |     1 |    60 |     2   (0)| 00:00:01 |   KEY |   KEY |<<<<<< Dynamic partition pruning
    ----------------------------------------------------------------------------------------------------------

    Predicate Information (identified by operation id):
    ---------------------------------------------------

       2 - filter("COL4"<=""(:B1) AND "COL4">=""(:B2))

    Note
    -----
       - dynamic statistics used: dynamic sampling (level=2)

    18 rows selected.

    SQL>

关键字DETERMINISTIC声明了:函数在给定相同的输入时,总会返回完全相同的输出。如果我们要用一个用户自定义函数来创建索引,那么这个关键字是必不可少的。通过这个关键字,Oracle就可以相信这个函数:只要提供相同的输入,不论这个函数调用多少次,它一定会返回相同的值。如果不是这样,通过索引访问数据时,可能会得到与全表扫描不同的答案。

Oracle中的DETERMINISTIC

 

   多次看到DETERMINISTIC,一直很疑惑,今天做了一个实验。我们欺骗ORACLE说是一个DETERMINISTIC函数,它在SQL中只调用一次。如果不使用DETERMINISTIC,可以看到出来的值都不一样。使用DETERMINISTIC后,不同的会话都出来一样的值。

SQL> create or replace function f_t(i_p int) return number DETERMINISTIC is

      i_rtn number;
    begin
      i_rtn := i_p * dbms_random.value(1,10);
      return i_rtn;
    end;
    /
函数已创建。

session1:
SQL> select LEVEL,f_t(1) FROM DUAL CONNECT BY LEVEL<=10;
     LEVEL     F_T(1)
---------- ----------
         1 2.55732959
         2 2.55732959
         3 2.55732959
         4 2.55732959
         5 2.55732959
         6 2.55732959
         7 2.55732959
         8 2.55732959
         9 2.55732959
        10 2.55732959
已选择10行。

session2:
SQL> select LEVEL,f_t(1) FROM DUAL CONNECT BY LEVEL<=10;
     LEVEL     F_T(1)
---------- ----------
         1 2.55732959
         2 2.55732959
         3 2.55732959
         4 2.55732959
         5 2.55732959
         6 2.55732959
         7 2.55732959
         8 2.55732959
         9 2.55732959
        10 2.55732959
已选择10行。


SQL> create or replace function f_t(i_p int) return number is
       i_rtn number;
    begin
       i_rtn := i_p * dbms_random.value(1,10);
       return i_rtn;
    end;
    /
函数已创建。


SQL> select LEVEL,f_t(1) FROM DUAL CONNECT BY LEVEL<=10;
     LEVEL     F_T(1)
---------- ----------
         1 8.48649118
         2  8.9396978
         3  2.2786135
         4 5.29205905
         5 5.32847713
         6 8.70095819
         7 6.20471031
         8 2.00101537
         9 3.53814265
        10 3.64991086
已选择10行。

Bug 35246239  Re-enable partition pruning in presence of non-deterministic functions as filter on partition key column

 This note gives a brief overview of bug 35246239.
 The content was last updated on: 26-AUG-2023
 Click here for details of each of the sections below.

Affects:

Product (Component) Oracle Server (Rdbms)
Range of versions believed to be affected Versions BELOW 23.1
Versions confirmed as being affected
  • (None Specified)
Platforms affected Generic (all / most platforms affected)

  Note that this fix can cause / expose the problem described in Bug:35601787

  Note that this fix has been superseded by the fix in Bug:35601787

Fixed:

This fix has been  superseded - please see the fixed version information for  Bug:35601787 . The box below only shows versions where the code change/s for 35246239 are first included - those versions may not contain the later improved fix.
 
The fix for 35246239 is first included in
  • (None Specified)

Symptoms:

Related To:

  • (None Specified)
  • Partitioned Tables

Description

Partition pruning is disabled for filter predicates on partition key
 column that involve non-deterministic PL/SQL functions.  This
 restriction was introduced by the fix in Bug 27175987.
  
 
Rediscovery information
 If you do not get partition pruning for predicates on the partition key that
 involve PL/SQL functions that have not been marked as deterministic, then you
 may have hit this bug.
  
Workaround
 None.

你可能感兴趣的:(java,数据库,jvm)