[20250714]使用or_expand提示遇到的疑惑.txt

[20250714]使用or_expand提示遇到的疑惑.txt

–//生产系统遇到的问题,使用or_expand提示,通过例子说明问题。

1.环境:

SCOTT@book01p> @ver2

==============================

PORT_STRING                   : x86_64/Linux 2.4.xx

VERSION                       : 21.0.0.0.0

BANNER                        : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 – Production

BANNER_FULL                   : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 – Production

Version 21.3.0.0.0

BANNER_LEGACY                 : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 – Production

CON_ID                        : 0

PL/SQL procedure successfully completed.

2.建立测试环境:

–//drop table t1 purge ;

create table t1 as select * from all_objects;

create index i_t1_object_id on t1(object_id);

–//create index i_t1_data_object_id on t1(data_object_id);

–//create index i_t1_object_name on t1(object_name);

–//分析表略。

–//当前仅仅建立object_id字段索引。

–//建立测试执行sql语句:

$ cat g1.txt

set term off

variable v_id number ;

variable v_did number ;

variable v_name varchar2(32) ;

exec :v_id := 76191;

exec :v_did := 76191;

exec :v_name := ‘DEPT’;

set term on

SELECT /*+ &&1 */

      t1.object_id

      ,t1.object_name

      ,t1.object_type

  FROM t1

 WHERE

       ( ( :v_did = ” OR :v_did IS NULL) OR data_object_id = :v_did)

and       ( ( :v_id = ” OR :v_id IS NULL) OR object_id = :v_id)

and       ( ( :v_name = ” OR :v_name IS NULL) OR object_name = :v_name)

;

–//注:主要模拟开发的写法,另外注意查询条件有索引的条件写在中间。

3.测试:

SCOTT@book01p> @ sl all

alter session set statistics_level = all;

Session altered.

SCOTT@book01p> @ g1.txt ”

 OBJECT_ID OBJECT_NAME                    OBJECT_TYPE

———- —————————— ——————————

     76191 DEPT                           TABLE

–//执行计划如下,在没有任何提示的情况下,执行计划选择全表扫描。

Plan hash value: 3617692013

——————————————————————————————————————–

| Id  | Operation         | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |

——————————————————————————————————————–

|   0 | SELECT STATEMENT  |      |      1 |        |       |   414 (100)|          |      1 |00:00:00.01 |    1486 |

|*  1 |  TABLE ACCESS FULL| T1   |      1 |      9 |   477 |   414   (1)| 00:00:01 |      1 |00:00:00.01 |    1486 |

——————————————————————————————————————–

Query Block Name / Object Alias (identified by operation id):

————————————————————-

   1 – SEL$1 / “T1″@”SEL$1”

Outline Data

————-

  /*+

      BEGIN_OUTLINE_DATA

      IGNORE_OPTIM_EMBEDDED_HINTS

      OPTIMIZER_FEATURES_ENABLE(‘21.1.0’)

      DB_VERSION(‘21.1.0’)

      ALL_ROWS

      OUTLINE_LEAF(@”SEL$1″)

      FULL(@”SEL$1″ “T1″@”SEL$1”)

      END_OUTLINE_DATA

  */

Peeked Binds (identified by position):

————————————–

   3 – (NUMBER, Primary=1)

   6 – (NUMBER, Primary=4)

   9 – (VARCHAR2(30), CSID=852, Primary=7)

Predicate Information (identified by operation id):

—————————————————

   1 – filter(((:V_ID IS NULL OR “OBJECT_ID”=:V_ID) AND (:V_DID IS NULL OR “DATA_OBJECT_ID”=:V_DID) AND

              (:V_NAME IS NULL OR “OBJECT_NAME”=:V_NAME)))

–//加入提示OR_EXPAND(@”SEL$1″)

SCOTT@book01p> @ g1.txt ‘OR_EXPAND(@”SEL$1″)’

OBJECT_ID OBJECT_NAME                    OBJECT_TYPE

———- —————————— ——————————

     76191 DEPT                           TABLE

–//执行计划如下:

Plan hash value: 3861657155

————————————————————————————————————————————-

| Id |Operation                              |Name           |Starts|E-Rows |E-Bytes|Cost (%CPU)|E-Time  |A-Rows|   A-Time  |Buffers|

————————————————————————————————————————————-

|   0|SELECT STATEMENT                       |               |     1|       |       |  416 (100)|        |     1|00:00:00.01|      4|

|   1| VIEW                                  |VW_ORE_BA8ECEFB|     1|   177 | 16284 |  416   (1)|00:00:01|     1|00:00:00.01|      4|

|   2|  UNION-ALL                            |               |     1|       |       |           |        |     1|00:00:00.01|      4|

|*  3|   FILTER                              |               |     1|       |       |           |        |     0|00:00:00.01|      0|

|*  4|    TABLE ACCESS FULL                  |T1             |     0|   176 |  9328 |  414   (1)|00:00:01|     0|00:00:00.01|      0|

|*  5|   FILTER                              |               |     1|       |       |           |        |     1|00:00:00.01|      4|

|*  6|    TABLE ACCESS BY INDEX ROWID BATCHED|T1             |     1|     1 |    53 |    2   (0)|00:00:01|     1|00:00:00.01|      4|

|*  7|     INDEX RANGE SCAN                  |I_T1_OBJECT_ID |     1|     1 |       |    1   (0)|00:00:01|     1|00:00:00.01|      3|

————————————————————————————————————————————-

Query Block Name / Object Alias (identified by operation id):

————————————————————-

   1 – SET$2A13AF86   / “VW_ORE_BA8ECEFB”@”SEL$BA8ECEFB”

   2 – SET$2A13AF86

   3 – SET$2A13AF86_1

   4 – SET$2A13AF86_1 / “T1″@”SET$2A13AF86_1”

   5 – SET$2A13AF86_2

   6 – SET$2A13AF86_2 / “T1″@”SET$2A13AF86_2”

   7 – SET$2A13AF86_2 / “T1″@”SET$2A13AF86_2”

Outline Data

————-

  /*+

      BEGIN_OUTLINE_DATA

      IGNORE_OPTIM_EMBEDDED_HINTS

      OPTIMIZER_FEATURES_ENABLE(‘21.1.0’)

      DB_VERSION(‘21.1.0’)

      ALL_ROWS

      OUTLINE_LEAF(@”SET$2A13AF86_2″)

      OUTLINE_LEAF(@”SET$2A13AF86_1″)

      OUTLINE_LEAF(@”SET$2A13AF86″)

      OUTLINE_LEAF(@”SEL$9162BF3C”)

      OR_EXPAND(@”SEL$1″ (1) (2))

      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

      OUTLINE(@”SEL$1″)

      NO_ACCESS(@”SEL$9162BF3C” “VW_ORE_BA8ECEFB”@”SEL$BA8ECEFB”)

      FULL(@”SET$2A13AF86_1″ “T1″@”SET$2A13AF86_1”)

      INDEX_RS_ASC(@”SET$2A13AF86_2″ “T1″@”SET$2A13AF86_2” (“T1″.”OBJECT_ID”))

      BATCH_TABLE_ACCESS_BY_ROWID(@”SET$2A13AF86_2″ “T1″@”SET$2A13AF86_2”)

      END_OUTLINE_DATA

  */

Peeked Binds (identified by position):

————————————–

   3 – (NUMBER, Primary=1)

   6 – (NUMBER, Primary=4)

   9 – (VARCHAR2(30), CSID=852, Primary=7)

Predicate Information (identified by operation id):

—————————————————

   3 – filter(:V_ID IS NULL)

   4 – filter(((:V_DID IS NULL OR “DATA_OBJECT_ID”=:V_DID) AND (:V_NAME IS NULL OR “OBJECT_NAME”=:V_NAME)))

   5 – filter(LNNVL(:V_ID IS NULL))

   6 – filter(((:V_DID IS NULL OR “DATA_OBJECT_ID”=:V_DID) AND (:V_NAME IS NULL OR “OBJECT_NAME”=:V_NAME)))

   7 – access(“OBJECT_ID”=:V_ID)

Hint Report (identified by operation id / Query Block Name / Object Alias):

Total hints for statement: 1

—————————————————————————

   5 –  SET$2A13AF86_2

           –  OR_EXPAND(@”SEL$1″)

–//注意实际上outline里面记录的是OR_EXPAND(@”SEL$1″ (1) (2))。

–//但是当我加入提示OR_EXPAND(@”SEL$1″ (1) (2))时会出现什么情况呢。

SCOTT@book01p> @ g1.txt ‘OR_EXPAND(@”SEL$1″ (1) (2))’

 OBJECT_ID OBJECT_NAME                    OBJECT_TYPE

———- —————————— ——————————

     76191 DEPT                           TABLE

–//执行计划如下:

COTT@book01p> @ dpc ” outline ”



Plan hash value: 3617692013

——————————————————————————————————————–

| Id  | Operation         | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |

——————————————————————————————————————–

|   0 | SELECT STATEMENT  |      |      1 |        |       |   414 (100)|          |      1 |00:00:00.01 |    1486 |

|*  1 |  TABLE ACCESS FULL| T1   |      1 |      9 |   477 |   414   (1)| 00:00:01 |      1 |00:00:00.01 |    1486 |

——————————————————————————————————————–

Query Block Name / Object Alias (identified by operation id):

————————————————————-

   1 – SEL$1 / “T1″@”SEL$1”

Outline Data

————-

  /*+

      BEGIN_OUTLINE_DATA

      IGNORE_OPTIM_EMBEDDED_HINTS

      OPTIMIZER_FEATURES_ENABLE(‘21.1.0’)

      DB_VERSION(‘21.1.0’)

      ALL_ROWS

      OUTLINE_LEAF(@”SEL$1″)

      FULL(@”SEL$1″ “T1″@”SEL$1”)

      END_OUTLINE_DATA

  */

Peeked Binds (identified by position):

————————————–

   3 – (NUMBER, Primary=1)

   6 – (NUMBER, Primary=4)

   9 – (VARCHAR2(30), CSID=852, Primary=7)

Predicate Information (identified by operation id):

—————————————————

   1 – filter(((:V_ID IS NULL OR “OBJECT_ID”=:V_ID) AND (:V_DID IS NULL OR “DATA_OBJECT_ID”=:V_DID) AND

              (:V_NAME IS NULL OR “OBJECT_NAME”=:V_NAME)))

Hint Report (identified by operation id / Query Block Name / Object Alias):

Total hints for statement: 1 (U – Unused (1))

—————————————————————————

   1 –  SEL$1

         U –  OR_EXPAND(@”SEL$1″ (1) (2))

–//执行计划反而时选择全表扫描。

–//可以抽取前面的outline,写成如下:

$ cat g2.txt

set term off

variable v_id number ;

variable v_did number ;

variable v_name varchar2(32) ;

exec :v_id := 76191;

exec :v_did := 76191;

exec :v_name := ‘DEPT’;

set term on

SELECT

 /*+

      BEGIN_OUTLINE_DATA

      IGNORE_OPTIM_EMBEDDED_HINTS

      OPTIMIZER_FEATURES_ENABLE(‘21.1.0’)

      DB_VERSION(‘21.1.0’)

      ALL_ROWS

      OUTLINE_LEAF(@”SET$2A13AF86_2″)

      OUTLINE_LEAF(@”SET$2A13AF86_1″)

      OUTLINE_LEAF(@”SET$2A13AF86″)

      OUTLINE_LEAF(@”SEL$9162BF3C”)

      OR_EXPAND(@”SEL$1″ (1) (2))

      OUTLINE(@”SEL$1″)

      NO_ACCESS(@”SEL$9162BF3C” “VW_ORE_BA8ECEFB”@”SEL$BA8ECEFB”)

      FULL(@”SET$2A13AF86_1″ “T1″@”SET$2A13AF86_1”)

      INDEX_RS_ASC(@”SET$2A13AF86_2″ “T1″@”SET$2A13AF86_2” (“T1″.”OBJECT_ID”))

      BATCH_TABLE_ACCESS_BY_ROWID(@”SET$2A13AF86_2″ “T1″@”SET$2A13AF86_2”)

      END_OUTLINE_DATA

  */

      t1.object_id

      ,t1.object_name

      ,t1.object_type

  FROM t1

 WHERE

       ( ( :v_did = ” OR :v_did IS NULL) OR data_object_id = :v_did)

and       ( ( :v_id = ” OR :v_id IS NULL) OR object_id = :v_id)

and       ( ( :v_name = ” OR :v_name IS NULL) OR object_name = :v_name)

;

–//执行发现执行计划还是选择全表扫描,结果不再贴出。

4.分析:

–//做10053分析:

SCOTT@book01p> @ g1.txt ‘OR_EXPAND(@”SEL$1″ )’

 OBJECT_ID OBJECT_NAME                    OBJECT_TYPE

———- —————————— ——————————

     76191 DEPT                           TABLE

SCOTT@book01p> @ hash

HASH_VALUE SQL_ID        CHILD_NUMBER KGL_BUCKET PLAN_HASH_VALUE HASH_HEX   SQL_EXEC_START      SQL_EXEC_ID

———- ————- ———— ———- ————— ———- ——————- ———–

1827272953 az74updqfmy7t            0     129273      3861657155  6ce9f8f9  2025-07-14 09:43:16    16777219

SCOTT@book01p> @ 10053x az74updqfmy7t 0

/u01/app/oracle/diag/rdbms/book/book/trace/book_ora_3990_aaz74updqfmy7t.trc

COTT@book01p> @ 10053y ”

TRCLINE

————————————————————————————————————————

Final query after transformations:******* UNPARSED QUERY IS *******

SELECT “VW_ORE_BA8ECEFB”.”ITEM_1″ “OBJECT_ID”,”VW_ORE_BA8ECEFB”.”ITEM_2″ “OBJECT_NAME”,”VW_ORE_BA8ECEFB”.”ITEM_3″ “OBJEC

T_TYPE” FROM  ( (SELECT “T1″.”OBJECT_ID” “ITEM_1″,”T1″.”OBJECT_NAME” “ITEM_2″,”T1″.”OBJECT_TYPE” “ITEM_3” FROM “SCOTT”.”

T1″ “T1” WHERE (:B1 IS NULL OR “T1”.”DATA_OBJECT_ID”=:B2) AND :B3 IS NULL AND (:B4 IS NULL OR “T1”.”OBJECT_NAME”=:B5)) U

NION ALL  (SELECT “T1″.”OBJECT_ID” “ITEM_1″,”T1″.”OBJECT_NAME” “ITEM_2″,”T1″.”OBJECT_TYPE” “ITEM_3” FROM “SCOTT”.”T1″ “T

1″ WHERE (:B6 IS NULL OR “T1”.”DATA_OBJECT_ID”=:B7) AND “T1”.”OBJECT_ID”=:B8 AND (:B9 IS NULL OR “T1”.”OBJECT_NAME”=:B10

) AND LNNVL(:B11 IS NULL))) “VW_ORE_BA8ECEFB”

–//格式化如下:

/* Formatted on 2025-07-14 09:47:56 (QP5 v5.277) */

SELECT “VW_ORE_BA8ECEFB”.”ITEM_1″ “OBJECT_ID”

      ,”VW_ORE_BA8ECEFB”.”ITEM_2″ “OBJECT_NAME”

      ,”VW_ORE_BA8ECEFB”.”ITEM_3″ “OBJECT_TYPE”

  FROM ( (SELECT “T1″.”OBJECT_ID” “ITEM_1”, “T1″.”OBJECT_NAME” “ITEM_2”, “T1″.”OBJECT_TYPE” “ITEM_3”

            FROM “SCOTT”.”T1″ “T1”

           WHERE     ( :B1 IS NULL OR “T1″.”DATA_OBJECT_ID” = :B2)

                 AND :B3 IS NULL

                 AND ( :B4 IS NULL OR “T1″.”OBJECT_NAME” = :B5))

        UNION ALL

        (SELECT “T1″.”OBJECT_ID” “ITEM_1”, “T1″.”OBJECT_NAME” “ITEM_2”, “T1″.”OBJECT_TYPE” “ITEM_3”

           FROM “SCOTT”.”T1″ “T1”

          WHERE     ( :B6 IS NULL OR “T1″.”DATA_OBJECT_ID” = :B7)

                AND “T1″.”OBJECT_ID” = :B8

                AND ( :B9 IS NULL OR “T1″.”OBJECT_NAME” = :B10)

                AND LNNVL ( :B11 IS NULL))) “VW_ORE_BA8ECEFB”

–//查看跟踪文件内容:

ORE:  Predicate list

P1 : (:B1 IS NULL OR “T1”.”DATA_OBJECT_ID”=:B2) AND (:B3 IS NULL OR “T1”.”OBJECT_ID”=:B4) AND (:B5 IS NULL OR “T1”.”OBJECT_NAME”=:B6)

P2 : :B1 IS NULL

P3 : “T1”.”OBJECT_ID”=:B1

P4 : :B1 IS NULL OR “T1”.”OBJECT_NAME”=:B2

 DNF Matrix (Before sorting OR branches)

            P1  P2  P3  P4

CNJ (#1) :   1   1   0   1

CNJ (#2) :   1   0   1   1

ORE:  Predicate list

P1 : (:B1 IS NULL OR “T1”.”DATA_OBJECT_ID”=:B2) AND (:B3 IS NULL OR “T1”.”OBJECT_ID”=:B4) AND (:B5 IS NULL OR “T1”.”OBJECT_NAME”=:B6)

P2 : :B1 IS NULL

P3 : “T1”.”OBJECT_ID”=:B1

P4 : :B1 IS NULL OR “T1”.”OBJECT_NAME”=:B2

 DNF Matrix (After OR branch sorting)

            P1  P2  P3  P4

CNJ (#1) :   1   1   0   1

CNJ (#2) :   1   0   1   1

–//oracle仅仅拆分2种情况,对应中间条件( ( :v_id = ” OR :v_id IS NULL) OR object_id = :v_id)。

–//实际上oracle将条件改写为(:v_id IS NULL OR object_id = :v_id).

–//注意不要被里面:b1,:b2之类绑定变量名字迷惑,非常容易误解。oracle重新命名的绑定变量名字,每行都是从B1开始。

–//另外oracle在上面的情况拆分存在问题,我的理解应该这样拆分。

P1 : :B1 IS NULL OR “T1”.”DATA_OBJECT_ID”=:B2

P2 : :B1 IS NULL

P3 : “T1”.”OBJECT_ID”=:B1

P4 : :B1 IS NULL OR “T1”.”OBJECT_NAME”=:B2

–//再来看看加入OR_EXPAND(@”SEL$1″ (1) (2))的情况。

SCOTT@book01p> @ g1.txt ‘OR_EXPAND(@”SEL$1″ (1) (2))’

 OBJECT_ID OBJECT_NAME                    OBJECT_TYPE

———- —————————— ——————————

     76191 DEPT                           TABLE

SCOTT@book01p> @ hashz

HASH_VALUE SQL_ID        CHILD_NUMBER KGL_BUCKET HASH_HEX   SQL_EXEC_START      SQL_EXEC_ID

———- ————- ———— ———- ———- ——————- ———–

1999013600 bs80ktjvkd1r0            0      34528  772686e0  2025-07-14 10:01:33    16777218

SCOTT@book01p> @ 10053x bs80ktjvkd1r0 0

/u01/app/oracle/diag/rdbms/book/book/trace/book_ora_3990_abs80ktjvkd1r0.trc

SCOTT@book01p> @ 10053y ”

TRCLINE

————————————————————————————————————————

Final query after transformations:******* UNPARSED QUERY IS *******

SELECT /*+  (1) (2)) */ “T1″.”OBJECT_ID” “OBJECT_ID”,”T1″.”OBJECT_NAME” “OBJECT_NAME”,”T1″.”OBJECT_TYPE” “OBJECT_TYPE” F

ROM “SCOTT”.”T1″ “T1” WHERE (:B1 IS NULL OR “T1”.”DATA_OBJECT_ID”=:B2) AND (:B3 IS NULL OR “T1”.”OBJECT_ID”=:B4) AND (:B

5 IS NULL OR “T1”.”OBJECT_NAME”=:B6)

–//转换后注解部分丢失OR_EXPAND。里面的绑定变量被替换为:Bn之类的变量名,注意这里转换后,在执行计划的Peeked Binds

–//(identified by position):部分看不见实际的绑定变量值。可以查看前面的执行计划。

–//查看跟踪文件内容:

ORE:  Predicate list

P1 : :B1 IS NULL

P2 : “T1”.”DATA_OBJECT_ID”=:B1

P3 : :B1 IS NULL

P4 : “T1”.”OBJECT_ID”=:B1

P5 : :B1 IS NULL

P6 : “T1”.”OBJECT_NAME”=:B1

 DNF Matrix (Before sorting OR branches)

            P1  P2  P3  P4  P5  P6

CNJ (#1) :   1   0   1   0   1   0

CNJ (#2) :   1   0   1   0   0   1

CNJ (#3) :   1   0   0   1   1   0

CNJ (#4) :   1   0   0   1   0   1

CNJ (#5) :   0   1   1   0   1   0

CNJ (#6) :   0   1   1   0   0   1

CNJ (#7) :   0   1   0   1   1   0

CNJ (#8) :   0   1   0   1   0   1

ORE:  Predicate list

P1 : :B1 IS NULL

P2 : “T1”.”DATA_OBJECT_ID”=:B1

P3 : :B1 IS NULL

P4 : “T1”.”OBJECT_ID”=:B1

P5 : :B1 IS NULL

P6 : “T1”.”OBJECT_NAME”=:B1

 DNF Matrix (After OR branch sorting)

            P1  P2  P3  P4  P5  P6

CNJ (#1) :   1   0   1   0   1   0

CNJ (#2) :   1   0   1   0   0   1

CNJ (#3) :   1   0   0   1   1   0

CNJ (#4) :   1   0   0   1   0   1

CNJ (#5) :   0   1   1   0   1   0

CNJ (#6) :   0   1   1   0   0   1

CNJ (#7) :   0   1   0   1   1   0

CNJ (#8) :   0   1   0   1   0   1

–//oracle仅仅拆分8种情况,在这样的情况下提示变成无效,选择全表扫描。

–//也就是在这样的情况直接使用OR_EXPAND(@”SEL$1″ (1) (2)))提示无效。

–//而使用提示 OR_EXPAND(@”SEL$1″ (1) (2) (3) (4) (5) (6) (7) (8) )有效。执行计划不再贴出。

–//oracle在处理这类or的优化时存在一些问题,后面的参数仅仅表示拆分的数量。

5.继续:

–//如果写成如下:

$ cat g1.txt

set term off

variable v_id number ;

variable v_did number ;

variable v_name varchar2(32) ;

exec :v_id := 76191;

exec :v_did := 76191;

exec :v_name := ‘DEPT’;

set term on

SELECT /*+ &&1 */

      t1.object_id

      ,t1.object_name

      ,t1.object_type

  FROM t1

 WHERE

—       ( ( :v_did = ” OR :v_did IS NULL) OR data_object_id = :v_did)

–and       ( ( :v_id = ” OR :v_id IS NULL) OR object_id = :v_id)

       ( ( :v_id = ” OR :v_id IS NULL) OR object_id = :v_id)

and       ( ( :v_did = ” OR :v_did IS NULL) OR data_object_id = :v_did)

and       ( ( :v_name = ” OR :v_name IS NULL) OR object_name = :v_name)

;

–//原来写在中间的查询条件放在前面。

SCOTT@book01p> @ g1.txt ‘OR_EXPAND(@”SEL$1″ )’

 OBJECT_ID OBJECT_NAME                    OBJECT_TYPE

———- —————————— ——————————

     76191 DEPT                           TABLE

SCOTT@book01p> @ hash

HASH_VALUE SQL_ID        CHILD_NUMBER KGL_BUCKET PLAN_HASH_VALUE HASH_HEX   SQL_EXEC_START      SQL_EXEC_ID

———- ————- ———— ———- ————— ———- ——————- ———–

2072084780 5kftshxxs309c            0      98604      3861657155  7b81812c  2025-07-14 15:59:20    16777218

–//执行计划如下:

Plan hash value: 3861657155

—————————————————————————————————————————————————-

| Id  | Operation                              | Name            | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |

—————————————————————————————————————————————————-

|   0 | SELECT STATEMENT                       |                 |      1 |        |       |   416 (100)|          |      1 |00:00:00.01 |       4 |

|   1 |  VIEW                                  | VW_ORE_BA8ECEFB |      1 |    177 | 16284 |   416   (1)| 00:00:01 |      1 |00:00:00.01 |       4 |

|   2 |   UNION-ALL                            |                 |      1 |        |       |            |          |      1 |00:00:00.01 |       4 |

|*  3 |    FILTER                              |                 |      1 |        |       |            |          |      0 |00:00:00.01 |       0 |

|*  4 |     TABLE ACCESS FULL                  | T1              |      0 |    176 |  9328 |   414   (1)| 00:00:01 |      0 |00:00:00.01 |       0 |

|*  5 |    FILTER                              |                 |      1 |        |       |            |          |      1 |00:00:00.01 |       4 |

|*  6 |     TABLE ACCESS BY INDEX ROWID BATCHED| T1              |      1 |      1 |    53 |     2   (0)| 00:00:01 |      1 |00:00:00.01 |       4 |

|*  7 |      INDEX RANGE SCAN                  | I_T1_OBJECT_ID  |      1 |      1 |       |     1   (0)| 00:00:01 |      1 |00:00:00.01 |       3 |

—————————————————————————————————————————————————-

Query Block Name / Object Alias (identified by operation id):

————————————————————-

   1 – SET$2A13AF86   / “VW_ORE_BA8ECEFB”@”SEL$BA8ECEFB”

   2 – SET$2A13AF86

   3 – SET$2A13AF86_1

   4 – SET$2A13AF86_1 / “T1″@”SET$2A13AF86_1”

   5 – SET$2A13AF86_2

   6 – SET$2A13AF86_2 / “T1″@”SET$2A13AF86_2”

   7 – SET$2A13AF86_2 / “T1″@”SET$2A13AF86_2”

Outline Data

————-

  /*+

      BEGIN_OUTLINE_DATA

      IGNORE_OPTIM_EMBEDDED_HINTS

      OPTIMIZER_FEATURES_ENABLE(‘21.1.0’)

      DB_VERSION(‘21.1.0’)

      ALL_ROWS

      OUTLINE_LEAF(@”SET$2A13AF86_2″)

      OUTLINE_LEAF(@”SET$2A13AF86_1″)

      OUTLINE_LEAF(@”SET$2A13AF86″)

      OUTLINE_LEAF(@”SEL$9162BF3C”)

      OR_EXPAND(@”SEL$1″ (1) (2))

      ~~~~~~~~~~~~~~~~~~~~~~~~~~~

      OUTLINE(@”SEL$1″)

      NO_ACCESS(@”SEL$9162BF3C” “VW_ORE_BA8ECEFB”@”SEL$BA8ECEFB”)

      FULL(@”SET$2A13AF86_1″ “T1″@”SET$2A13AF86_1”)

      INDEX_RS_ASC(@”SET$2A13AF86_2″ “T1″@”SET$2A13AF86_2” (“T1″.”OBJECT_ID”))

      BATCH_TABLE_ACCESS_BY_ROWID(@”SET$2A13AF86_2″ “T1″@”SET$2A13AF86_2”)

      END_OUTLINE_DATA

  */

Peeked Binds (identified by position):

————————————–

   3 – (NUMBER, Primary=1)

   6 – (NUMBER, Primary=4)

   9 – (VARCHAR2(30), CSID=852, Primary=7)

Predicate Information (identified by operation id):

—————————————————

   3 – filter(:V_ID IS NULL)

   4 – filter(((:V_DID IS NULL OR “DATA_OBJECT_ID”=:V_DID) AND (:V_NAME IS NULL OR “OBJECT_NAME”=:V_NAME)))

   5 – filter(LNNVL(:V_ID IS NULL))

   6 – filter(((:V_DID IS NULL OR “DATA_OBJECT_ID”=:V_DID) AND (:V_NAME IS NULL OR “OBJECT_NAME”=:V_NAME)))

   7 – access(“OBJECT_ID”=:V_ID)

Hint Report (identified by operation id / Query Block Name / Object Alias):

Total hints for statement: 1

—————————————————————————

   5 –  SET$2A13AF86_2

           –  OR_EXPAND(@”SEL$1″ )

–//注意看下划线,OR_EXPAND(@”SEL$1″ (1) (2))。如果再次执行采用OR_EXPAND(@”SEL$1″ (1) (2))提示,执行计划还是选择全表扫描。

SCOTT@book01p> @ 10053x 5kftshxxs309c 0

/u01/app/oracle/diag/rdbms/book/book/trace/book_ora_3640_a5kftshxxs309c.trc

SCOTT@book01p> @ 10053y ”

TRCLINE

————————————————————————————————————————

Final query after transformations:******* UNPARSED QUERY IS *******

SELECT “VW_ORE_BA8ECEFB”.”ITEM_1″ “OBJECT_ID”,”VW_ORE_BA8ECEFB”.”ITEM_2″ “OBJECT_NAME”,”VW_ORE_BA8ECEFB”.”ITEM_3″ “OBJEC

T_TYPE” FROM  ( (SELECT “T1″.”OBJECT_ID” “ITEM_1″,”T1″.”OBJECT_NAME” “ITEM_2″,”T1″.”OBJECT_TYPE” “ITEM_3” FROM “SCOTT”.”

T1″ “T1” WHERE :B1 IS NULL AND (:B2 IS NULL OR “T1”.”DATA_OBJECT_ID”=:B3) AND (:B4 IS NULL OR “T1”.”OBJECT_NAME”=:B5)) U

NION ALL  (SELECT “T1″.”OBJECT_ID” “ITEM_1″,”T1″.”OBJECT_NAME” “ITEM_2″,”T1″.”OBJECT_TYPE” “ITEM_3” FROM “SCOTT”.”T1″ “T

1″ WHERE “T1”.”OBJECT_ID”=:B6 AND (:B7 IS NULL OR “T1”.”DATA_OBJECT_ID”=:B8) AND (:B9 IS NULL OR “T1”.”OBJECT_NAME”=:B10

) AND LNNVL(:B11 IS NULL))) “VW_ORE_BA8ECEFB”

–//格式化如下:

SELECT “VW_ORE_BA8ECEFB”.”ITEM_1″ “OBJECT_ID”

      ,”VW_ORE_BA8ECEFB”.”ITEM_2″ “OBJECT_NAME”

      ,”VW_ORE_BA8ECEFB”.”ITEM_3″ “OBJECT_TYPE”

  FROM ( (SELECT “T1″.”OBJECT_ID” “ITEM_1”, “T1″.”OBJECT_NAME” “ITEM_2”, “T1″.”OBJECT_TYPE” “ITEM_3”

            FROM “SCOTT”.”T1″ “T1”

           WHERE     :B1 IS NULL

                 AND ( :B2 IS NULL OR “T1″.”DATA_OBJECT_ID” = :B3)

                 AND ( :B4 IS NULL OR “T1″.”OBJECT_NAME” = :B5))

        UNION ALL

        (SELECT “T1″.”OBJECT_ID” “ITEM_1”, “T1″.”OBJECT_NAME” “ITEM_2”, “T1″.”OBJECT_TYPE” “ITEM_3”

           FROM “SCOTT”.”T1″ “T1”

          WHERE     “T1″.”OBJECT_ID” = :B6

                AND ( :B7 IS NULL OR “T1″.”DATA_OBJECT_ID” = :B8)

                AND ( :B9 IS NULL OR “T1″.”OBJECT_NAME” = :B10)

                AND LNNVL ( :B11 IS NULL))) “VW_ORE_BA8ECEFB”

–//查看跟踪文件内容:                

ORE:  Predicate list

P1 : :B1 IS NULL

P2 : “T1”.”OBJECT_ID”=:B1

P3 : (:B1 IS NULL OR “T1”.”DATA_OBJECT_ID”=:B2) AND (:B3 IS NULL OR “T1”.”OBJECT_NAME”=:B4)

P4 : :B1 IS NULL OR “T1”.”OBJECT_NAME”=:B2

 DNF Matrix (Before sorting OR branches)

            P1  P2  P3  P4

CNJ (#1) :   1   0   1   1

CNJ (#2) :   0   1   1   1

ORE:  Predicate list

P1 : :B1 IS NULL

P2 : “T1”.”OBJECT_ID”=:B1

P3 : (:B1 IS NULL OR “T1”.”DATA_OBJECT_ID”=:B2) AND (:B3 IS NULL OR “T1”.”OBJECT_NAME”=:B4)

P4 : :B1 IS NULL OR “T1”.”OBJECT_NAME”=:B2

 DNF Matrix (After OR branch sorting)

            P1  P2  P3  P4

CNJ (#1) :   1   0   1   1

CNJ (#2) :   0   1   1   1

–//拆分确实不好理解为什么这样操作。

6.小结:

–//使用or_expand提示优化要做一些尝试,如果建立data_object_id索引,object_name索引,可能会发生执行计划的变化。

–//另外无法使用sql profile交换的方式控制执行计划,除非修改里面的提示OR_EXPAND(@”SEL$1″ )。

–//使用sql patch的方式情况也是类似,像前面的情况如果OR_EXPAND(@”SEL$1″ (1) (2) )打补丁,执行计划选择全表扫描。

–//如果建立如下索引:

create index i_t1_data_object_id on t1(data_object_id);

SCOTT@book01p> @ g1.txt ‘OR_EXPAND(@”SEL$1″  )’

 OBJECT_ID OBJECT_NAME                    OBJECT_TYPE

———- —————————— ——————————

     76191 DEPT                           TABLE

–//执行计划如下:

Plan hash value: 546662753

——————————————————————————————————————————————————–

| Id  | Operation                              | Name                | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |

——————————————————————————————————————————————————–

|   0 | SELECT STATEMENT                       |                     |      1 |        |       |   420 (100)|          |      1 |00:00:00.01 |       4 |

|   1 |  VIEW                                  | VW_ORE_BA8ECEFB     |      1 |   3512 |   315K|   420   (1)| 00:00:01 |      1 |00:00:00.01 |       4 |

|   2 |   UNION-ALL                            |                     |      1 |        |       |            |          |      1 |00:00:00.01 |       4 |

|*  3 |    FILTER                              |                     |      1 |        |       |            |          |      0 |00:00:00.01 |       0 |

|*  4 |     TABLE ACCESS FULL                  | T1                  |      0 |   3509 |   174K|   414   (1)| 00:00:01 |      0 |00:00:00.01 |       0 |

|*  5 |    FILTER                              |                     |      1 |        |       |            |          |      0 |00:00:00.01 |       0 |

|*  6 |     TABLE ACCESS BY INDEX ROWID BATCHED| T1                  |      0 |      1 |    53 |     2   (0)| 00:00:01 |      0 |00:00:00.01 |       0 |

|*  7 |      INDEX RANGE SCAN                  | I_T1_DATA_OBJECT_ID |      0 |      1 |       |     1   (0)| 00:00:01 |      0 |00:00:00.01 |       0 |

|*  8 |    FILTER                              |                     |      1 |        |       |            |          |      0 |00:00:00.01 |       0 |

|*  9 |     TABLE ACCESS BY INDEX ROWID BATCHED| T1                  |      0 |      1 |    53 |     2   (0)| 00:00:01 |      0 |00:00:00.01 |       0 |

|* 10 |      INDEX RANGE SCAN                  | I_T1_OBJECT_ID      |      0 |      1 |       |     1   (0)| 00:00:01 |      0 |00:00:00.01 |       0 |

|* 11 |    FILTER                              |                     |      1 |        |       |            |          |      1 |00:00:00.01 |       4 |

|* 12 |     TABLE ACCESS BY INDEX ROWID BATCHED| T1                  |      1 |      1 |    53 |     2   (0)| 00:00:01 |      1 |00:00:00.01 |       4 |

|* 13 |      INDEX RANGE SCAN                  | I_T1_OBJECT_ID      |      1 |      1 |       |     1   (0)| 00:00:01 |      1 |00:00:00.01 |       3 |

——————————————————————————————————————————————————–

Query Block Name / Object Alias (identified by operation id):

————————————————————-

   1 – SET$171C43EC   / “VW_ORE_BA8ECEFB”@”SEL$BA8ECEFB”

   2 – SET$171C43EC

   3 – SET$171C43EC_1

   4 – SET$171C43EC_1 / “T1″@”SET$171C43EC_1”

   5 – SET$171C43EC_2

   6 – SET$171C43EC_2 / “T1″@”SET$171C43EC_2”

   7 – SET$171C43EC_2 / “T1″@”SET$171C43EC_2”

   8 – SET$171C43EC_3

   9 – SET$171C43EC_3 / “T1″@”SET$171C43EC_3”

  10 – SET$171C43EC_3 / “T1″@”SET$171C43EC_3”

  11 – SET$171C43EC_4

  12 – SET$171C43EC_4 / “T1″@”SET$171C43EC_4”

  13 – SET$171C43EC_4 / “T1″@”SET$171C43EC_4”

Outline Data

————-

  /*+

      BEGIN_OUTLINE_DATA

      IGNORE_OPTIM_EMBEDDED_HINTS

      OPTIMIZER_FEATURES_ENABLE(‘21.1.0’)

      DB_VERSION(‘21.1.0’)

      ALL_ROWS

      OUTLINE_LEAF(@”SET$171C43EC_4″)

      OUTLINE_LEAF(@”SET$171C43EC_3″)

      OUTLINE_LEAF(@”SET$171C43EC_2″)

      OUTLINE_LEAF(@”SET$171C43EC_1″)

      OUTLINE_LEAF(@”SET$171C43EC”)

      OUTLINE_LEAF(@”SEL$47D9A6EC”)

      OR_EXPAND(@”SEL$1″ (1) (2) (3) (4))

      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

      OUTLINE(@”SEL$1″)

      NO_ACCESS(@”SEL$47D9A6EC” “VW_ORE_BA8ECEFB”@”SEL$BA8ECEFB”)

      FULL(@”SET$171C43EC_1″ “T1″@”SET$171C43EC_1”)

      INDEX_RS_ASC(@”SET$171C43EC_2″ “T1″@”SET$171C43EC_2” (“T1″.”DATA_OBJECT_ID”))

      BATCH_TABLE_ACCESS_BY_ROWID(@”SET$171C43EC_2″ “T1″@”SET$171C43EC_2”)

      INDEX_RS_ASC(@”SET$171C43EC_3″ “T1″@”SET$171C43EC_3” (“T1″.”OBJECT_ID”))

      BATCH_TABLE_ACCESS_BY_ROWID(@”SET$171C43EC_3″ “T1″@”SET$171C43EC_3”)

      INDEX_RS_ASC(@”SET$171C43EC_4″ “T1″@”SET$171C43EC_4” (“T1″.”OBJECT_ID”))

      BATCH_TABLE_ACCESS_BY_ROWID(@”SET$171C43EC_4″ “T1″@”SET$171C43EC_4”)

      END_OUTLINE_DATA

  */

Peeked Binds (identified by position):

————————————–

   3 – (NUMBER, Primary=1)

   6 – (NUMBER, Primary=4)

   9 – (VARCHAR2(30), CSID=852, Primary=7)

Predicate Information (identified by operation id):

—————————————————

   3 – filter((:V_DID IS NULL AND :V_ID IS NULL))

   4 – filter((:V_NAME IS NULL OR “OBJECT_NAME”=:V_NAME))

   5 – filter((LNNVL(:V_DID IS NULL) AND :V_ID IS NULL))

   6 – filter((:V_NAME IS NULL OR “OBJECT_NAME”=:V_NAME))

   7 – access(“DATA_OBJECT_ID”=:V_DID)

   8 – filter((LNNVL(:V_ID IS NULL) AND :V_DID IS NULL))

   9 – filter((:V_NAME IS NULL OR “OBJECT_NAME”=:V_NAME))

  10 – access(“OBJECT_ID”=:V_ID)

  11 – filter((LNNVL(:V_DID IS NULL) AND LNNVL(:V_ID IS NULL)))

  12 – filter((“DATA_OBJECT_ID”=:V_DID AND (:V_NAME IS NULL OR “OBJECT_NAME”=:V_NAME)))

  13 – access(“OBJECT_ID”=:V_ID)

Hint Report (identified by operation id / Query Block Name / Object Alias):

Total hints for statement: 1

—————————————————————————

  11 –  SET$171C43EC_4

           –  OR_EXPAND(@”SEL$1″  )

–//而执行使用提示:

SCOTT@book01p> @ g1.txt ‘OR_EXPAND(@”SEL$1″ (1) (2) (3) (4) )’

 OBJECT_ID OBJECT_NAME                    OBJECT_TYPE

———- —————————— ——————————

     76191 DEPT                           TABLE

–//执行计划如下:

Plan hash value: 523270132

————————————————————————————————————————————————–

| Id |Operation                              | Name            | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |

————————————————————————————————————————————————–

|   0|SELECT STATEMENT                       |                 |      1 |        |       |   831 (100)|          |      1 |00:00:00.01 |       4 |

|   1| VIEW                                  | VW_ORE_BA8ECEFB |      1 |   3512 |   315K|   831   (1)| 00:00:01 |      1 |00:00:00.01 |       4 |

|   2|  UNION-ALL                            |                 |      1 |        |       |            |          |      1 |00:00:00.01 |       4 |

|*  3|   FILTER                              |                 |      1 |        |       |            |          |      0 |00:00:00.01 |       0 |

|*  4|    TABLE ACCESS FULL                  | T1              |      0 |   3509 |   181K|   414   (1)| 00:00:01 |      0 |00:00:00.01 |       0 |

|*  5|   FILTER                              |                 |      1 |        |       |            |          |      0 |00:00:00.01 |       0 |

|*  6|    TABLE ACCESS FULL                  | T1              |      0 |      1 |    53 |   414   (1)| 00:00:01 |      0 |00:00:00.01 |       0 |

|*  7|   FILTER                              |                 |      1 |        |       |            |          |      0 |00:00:00.01 |       0 |

|*  8|    TABLE ACCESS BY INDEX ROWID BATCHED| T1              |      0 |      1 |    53 |     2   (0)| 00:00:01 |      0 |00:00:00.01 |       0 |

|*  9|     INDEX RANGE SCAN                  | I_T1_OBJECT_ID  |      0 |      1 |       |     1   (0)| 00:00:01 |      0 |00:00:00.01 |       0 |

|* 10|   FILTER                              |                 |      1 |        |       |            |          |      1 |00:00:00.01 |       4 |

|* 11|    TABLE ACCESS BY INDEX ROWID BATCHED| T1              |      1 |      1 |    53 |     2   (0)| 00:00:01 |      1 |00:00:00.01 |       4 |

|* 12|     INDEX RANGE SCAN                  | I_T1_OBJECT_ID  |      1 |      1 |       |     1   (0)| 00:00:01 |      1 |00:00:00.01 |       3 |

————————————————————————————————————————————————–

Query Block Name / Object Alias (identified by operation id):

————————————————————-

   1 – SET$171C43EC   / “VW_ORE_BA8ECEFB”@”SEL$BA8ECEFB”

   2 – SET$171C43EC

   3 – SET$171C43EC_1

   4 – SET$171C43EC_1 / “T1″@”SET$171C43EC_1”

   5 – SET$171C43EC_2

   6 – SET$171C43EC_2 / “T1″@”SET$171C43EC_2”

   7 – SET$171C43EC_3

   8 – SET$171C43EC_3 / “T1″@”SET$171C43EC_3”

   9 – SET$171C43EC_3 / “T1″@”SET$171C43EC_3”

  10 – SET$171C43EC_4

  11 – SET$171C43EC_4 / “T1″@”SET$171C43EC_4”

  12 – SET$171C43EC_4 / “T1″@”SET$171C43EC_4”

Outline Data

————-

  /*+

      BEGIN_OUTLINE_DATA

      IGNORE_OPTIM_EMBEDDED_HINTS

      OPTIMIZER_FEATURES_ENABLE(‘21.1.0’)

      DB_VERSION(‘21.1.0’)

      ALL_ROWS

      OUTLINE_LEAF(@”SET$171C43EC_4″)

      OUTLINE_LEAF(@”SET$171C43EC_3″)

      OUTLINE_LEAF(@”SET$171C43EC_2″)

      OUTLINE_LEAF(@”SET$171C43EC_1″)

      OUTLINE_LEAF(@”SET$171C43EC”)

      OUTLINE_LEAF(@”SEL$47D9A6EC”)

      OR_EXPAND(@”SEL$1″ (1) (2) (3) (4))

      OUTLINE(@”SEL$1″)

      NO_ACCESS(@”SEL$47D9A6EC” “VW_ORE_BA8ECEFB”@”SEL$BA8ECEFB”)

      FULL(@”SET$171C43EC_1″ “T1″@”SET$171C43EC_1”)

      FULL(@”SET$171C43EC_2″ “T1″@”SET$171C43EC_2”)

      INDEX_RS_ASC(@”SET$171C43EC_3″ “T1″@”SET$171C43EC_3” (“T1″.”OBJECT_ID”))

      BATCH_TABLE_ACCESS_BY_ROWID(@”SET$171C43EC_3″ “T1″@”SET$171C43EC_3”)

      INDEX_RS_ASC(@”SET$171C43EC_4″ “T1″@”SET$171C43EC_4” (“T1″.”OBJECT_ID”))

      BATCH_TABLE_ACCESS_BY_ROWID(@”SET$171C43EC_4″ “T1″@”SET$171C43EC_4”)

      END_OUTLINE_DATA

  */

Peeked Binds (identified by position):

————————————–

   3 – (NUMBER, Primary=1)

   6 – (NUMBER, Primary=4)

   9 – (VARCHAR2(30), CSID=852, Primary=7)

Predicate Information (identified by operation id):

—————————————————

   3 – filter((:V_NAME IS NULL AND :V_ID IS NULL))

   4 – filter((:V_DID IS NULL OR “DATA_OBJECT_ID”=:V_DID))

   5 – filter((LNNVL(:V_NAME IS NULL) AND :V_ID IS NULL))

   6 – filter((“OBJECT_NAME”=:V_NAME AND (:V_DID IS NULL OR “DATA_OBJECT_ID”=:V_DID)))

   7 – filter((LNNVL(:V_ID IS NULL) AND :V_NAME IS NULL))

   8 – filter((:V_DID IS NULL OR “DATA_OBJECT_ID”=:V_DID))

   9 – access(“OBJECT_ID”=:V_ID)

  10 – filter((LNNVL(:V_NAME IS NULL) AND LNNVL(:V_ID IS NULL)))

  11 – filter((“OBJECT_NAME”=:V_NAME AND (:V_DID IS NULL OR “DATA_OBJECT_ID”=:V_DID)))

  12 – access(“OBJECT_ID”=:V_ID)

Hint Report (identified by operation id / Query Block Name / Object Alias):

Total hints for statement: 1

—————————————————————————

  10 –  SET$171C43EC_4

           –  OR_EXPAND(@”SEL$1″ (1) (2) (3) (4) )

–//前后对比,可以发现实际上2个执行计划完全不同,前面会使用I_T1_DATA_OBJECT_ID索引,而后者根本不会。

–//虽然outline记录的提示都是OR_EXPAND(@”SEL$1″ (1) (2) (3) (4) )。

–//有点无法理解的是这样情况下使用OR_EXPAND(@”SEL$1″ (1) (2) (3) (4) (5) (6) (7) (8) )提示,执行计划又选择全表扫描。

–//查看10053跟踪文件:

ORE:  Predicate list

P1 : :B1 IS NULL

P2 : “T1”.”OBJECT_ID”=:B1

P3 : (:B1 IS NULL OR “T1”.”DATA_OBJECT_ID”=:B2) AND (:B3 IS NULL OR “T1”.”OBJECT_NAME”=:B4)

P4 : :B1 IS NULL

P5 : “T1”.”OBJECT_NAME”=:B1

 DNF Matrix (After OR branch sorting)

            P1  P2  P3  P4  P5

CNJ (#1) :   1   0   1   1   0

CNJ (#2) :   1   0   1   0   1

CNJ (#3) :   0   1   1   1   0

CNJ (#4) :   0   1   1   0   1

–//总之,在优化使用提示or_expand提示时注意这些细节,即使使用sql patch也可能在不小心导致执行计划发生变化,无法很好的控制

–//执行计划。

–//最后建议开发还是少使用这些所谓的技巧,少写这类风格的sql语句,在我看来这类sql语句根本不允许出现在生产系统中。

–//你可以再尝试建立索引:

–//create index i_t1_object_name on t1(object_name);

SCOTT@book01p> @ g1.txt ‘OR_EXPAND(@”SEL$1″ )’

 OBJECT_ID OBJECT_NAME                    OBJECT_TYPE

———- —————————— ——————————

     76191 DEPT                           TABLE

Plan hash value: 2061367055

—————————————————————————————————————————————-

| Id |Operation                              |Name               |Starts|E-Rows|E-Bytes|Cost (%CPU)|E-Time  |A-Rows|   A-Time  |Buffers|

—————————————————————————————————————————————-

|   0|SELECT STATEMENT                       |                   |     1|      |       |  430 (100)|        |     1|00:00:00.01|      4|

|   1| VIEW                                  |VW_ORE_BA8ECEFB    |     1| 70174|  6304K|  430   (1)|00:00:01|     1|00:00:00.01|      4|

|   2|  UNION-ALL                            |                   |     1|      |       |           |        |     1|00:00:00.01|      4|

|*  3|   FILTER                              |                   |     1|      |       |           |        |     0|00:00:00.01|      0|

|   4|    TABLE ACCESS FULL                  |T1                 |     0| 70167|  3494K|  414   (1)|00:00:01|     0|00:00:00.01|      0|

|*  5|   FILTER                              |                   |     1|      |       |           |        |     0|00:00:00.01|      0|

|   6|    TABLE ACCESS BY INDEX ROWID BATCHED|T1                 |     0|     1|    51 |    4   (0)|00:00:01|     0|00:00:00.01|      0|

|*  7|     INDEX RANGE SCAN                  |I_T1_OBJECT_NAME   |     0|     1|       |    3   (0)|00:00:01|     0|00:00:00.01|      0|

|*  8|   FILTER                              |                   |     1|      |       |           |        |     0|00:00:00.01|      0|

|   9|    TABLE ACCESS BY INDEX ROWID BATCHED|T1                 |     0|     1|    53 |    2   (0)|00:00:01|     0|00:00:00.01|      0|

|* 10|     INDEX RANGE SCAN                  |I_T1_DATA_OBJECT_ID|     0|     1|       |    1   (0)|00:00:01|     0|00:00:00.01|      0|

|* 11|   FILTER                              |                   |     1|      |       |           |        |     0|00:00:00.01|      0|

|* 12|    TABLE ACCESS BY INDEX ROWID BATCHED|T1                 |     0|     1|    53 |    2   (0)|00:00:01|     0|00:00:00.01|      0|

|* 13|     INDEX RANGE SCAN                  |I_T1_DATA_OBJECT_ID|     0|     1|       |    1   (0)|00:00:01|     0|00:00:00.01|      0|

|* 14|   FILTER                              |                   |     1|      |       |           |        |     0|00:00:00.01|      0|

|  15|    TABLE ACCESS BY INDEX ROWID BATCHED|T1                 |     0|     1|    53 |    2   (0)|00:00:01|     0|00:00:00.01|      0|

|* 16|     INDEX RANGE SCAN                  |I_T1_OBJECT_ID     |     0|     1|       |    1   (0)|00:00:01|     0|00:00:00.01|      0|

|* 17|   FILTER                              |                   |     1|      |       |           |        |     0|00:00:00.01|      0|

|* 18|    TABLE ACCESS BY INDEX ROWID BATCHED|T1                 |     0|     1|    53 |    2   (0)|00:00:01|     0|00:00:00.01|      0|

|* 19|     INDEX RANGE SCAN                  |I_T1_OBJECT_ID     |     0|     1|       |    1   (0)|00:00:01|     0|00:00:00.01|      0|

|* 20|   FILTER                              |                   |     1|      |       |           |        |     0|00:00:00.01|      0|

|* 21|    TABLE ACCESS BY INDEX ROWID BATCHED|T1                 |     0|     1|    53 |    2   (0)|00:00:01|     0|00:00:00.01|      0|

|* 22|     INDEX RANGE SCAN                  |I_T1_OBJECT_ID     |     0|     1|       |    1   (0)|00:00:01|     0|00:00:00.01|      0|

|* 23|   FILTER                              |                   |     1|      |       |           |        |     1|00:00:00.01|      4|

|* 24|    TABLE ACCESS BY INDEX ROWID BATCHED|T1                 |     1|     1|    53 |    2   (0)|00:00:01|     1|00:00:00.01|      4|

|* 25|     INDEX RANGE SCAN                  |I_T1_OBJECT_ID     |     1|     1|       |    1   (0)|00:00:01|     1|00:00:00.01|      3|

—————————————————————————————————————————————-

Query Block Name / Object Alias (identified by operation id):

————————————————————-

   1 – SET$B2C621EA   / “VW_ORE_BA8ECEFB”@”SEL$BA8ECEFB”

   2 – SET$B2C621EA

   3 – SET$B2C621EA_1

   4 – SET$B2C621EA_1 / “T1″@”SET$B2C621EA_1”

   5 – SET$B2C621EA_2

   6 – SET$B2C621EA_2 / “T1″@”SET$B2C621EA_2”

   7 – SET$B2C621EA_2 / “T1″@”SET$B2C621EA_2”

   8 – SET$B2C621EA_3

   9 – SET$B2C621EA_3 / “T1″@”SET$B2C621EA_3”

  10 – SET$B2C621EA_3 / “T1″@”SET$B2C621EA_3”

  11 – SET$B2C621EA_4

  12 – SET$B2C621EA_4 / “T1″@”SET$B2C621EA_4”

  13 – SET$B2C621EA_4 / “T1″@”SET$B2C621EA_4”

  14 – SET$B2C621EA_5

  15 – SET$B2C621EA_5 / “T1″@”SET$B2C621EA_5”

  16 – SET$B2C621EA_5 / “T1″@”SET$B2C621EA_5”

  17 – SET$B2C621EA_6

  18 – SET$B2C621EA_6 / “T1″@”SET$B2C621EA_6”

  19 – SET$B2C621EA_6 / “T1″@”SET$B2C621EA_6”

  20 – SET$B2C621EA_7

  21 – SET$B2C621EA_7 / “T1″@”SET$B2C621EA_7”

  22 – SET$B2C621EA_7 / “T1″@”SET$B2C621EA_7”

  23 – SET$B2C621EA_8

  24 – SET$B2C621EA_8 / “T1″@”SET$B2C621EA_8”

  25 – SET$B2C621EA_8 / “T1″@”SET$B2C621EA_8”

Outline Data

————-

  /*+

      BEGIN_OUTLINE_DATA

      IGNORE_OPTIM_EMBEDDED_HINTS

      OPTIMIZER_FEATURES_ENABLE(‘21.1.0’)

      DB_VERSION(‘21.1.0’)

      ALL_ROWS

      OUTLINE_LEAF(@”SET$B2C621EA_8″)

      OUTLINE_LEAF(@”SET$B2C621EA_7″)

      OUTLINE_LEAF(@”SET$B2C621EA_6″)

      OUTLINE_LEAF(@”SET$B2C621EA_5″)

      OUTLINE_LEAF(@”SET$B2C621EA_4″)

      OUTLINE_LEAF(@”SET$B2C621EA_3″)

      OUTLINE_LEAF(@”SET$B2C621EA_2″)

      OUTLINE_LEAF(@”SET$B2C621EA_1″)

      OUTLINE_LEAF(@”SET$B2C621EA”)

      OUTLINE_LEAF(@”SEL$DC109C8D”)

      OR_EXPAND(@”SEL$1″ (1) (2) (3) (4) (5) (6) (7) (8))

      OUTLINE(@”SEL$1″)

      NO_ACCESS(@”SEL$DC109C8D” “VW_ORE_BA8ECEFB”@”SEL$BA8ECEFB”)

      FULL(@”SET$B2C621EA_1″ “T1″@”SET$B2C621EA_1”)

      INDEX_RS_ASC(@”SET$B2C621EA_2″ “T1″@”SET$B2C621EA_2” (“T1″.”OBJECT_NAME”))

      BATCH_TABLE_ACCESS_BY_ROWID(@”SET$B2C621EA_2″ “T1″@”SET$B2C621EA_2”)

      INDEX_RS_ASC(@”SET$B2C621EA_3″ “T1″@”SET$B2C621EA_3” (“T1″.”DATA_OBJECT_ID”))

      BATCH_TABLE_ACCESS_BY_ROWID(@”SET$B2C621EA_3″ “T1″@”SET$B2C621EA_3”)

      INDEX_RS_ASC(@”SET$B2C621EA_4″ “T1″@”SET$B2C621EA_4” (“T1″.”DATA_OBJECT_ID”))

      BATCH_TABLE_ACCESS_BY_ROWID(@”SET$B2C621EA_4″ “T1″@”SET$B2C621EA_4”)

      INDEX_RS_ASC(@”SET$B2C621EA_5″ “T1″@”SET$B2C621EA_5” (“T1″.”OBJECT_ID”))

      BATCH_TABLE_ACCESS_BY_ROWID(@”SET$B2C621EA_5″ “T1″@”SET$B2C621EA_5”)

      INDEX_RS_ASC(@”SET$B2C621EA_6″ “T1″@”SET$B2C621EA_6” (“T1″.”OBJECT_ID”))

      BATCH_TABLE_ACCESS_BY_ROWID(@”SET$B2C621EA_6″ “T1″@”SET$B2C621EA_6”)

      INDEX_RS_ASC(@”SET$B2C621EA_7″ “T1″@”SET$B2C621EA_7” (“T1″.”OBJECT_ID”))

      BATCH_TABLE_ACCESS_BY_ROWID(@”SET$B2C621EA_7″ “T1″@”SET$B2C621EA_7”)

      INDEX_RS_ASC(@”SET$B2C621EA_8″ “T1″@”SET$B2C621EA_8” (“T1″.”OBJECT_ID”))

      BATCH_TABLE_ACCESS_BY_ROWID(@”SET$B2C621EA_8″ “T1″@”SET$B2C621EA_8”)

      END_OUTLINE_DATA

  */

Peeked Binds (identified by position):

————————————–

   3 – (NUMBER, Primary=1)

   6 – (NUMBER, Primary=4)

   9 – (VARCHAR2(30), CSID=852, Primary=7)

Peeked Binds (identified by position):

————————————–

   3 – (NUMBER, Primary=1)

   6 – (NUMBER, Primary=4)

   9 – (VARCHAR2(30), CSID=852, Primary=7)

Predicate Information (identified by operation id):

—————————————————

   3 – filter((:V_NAME IS NULL AND :V_DID IS NULL AND :V_ID IS NULL))

   5 – filter((LNNVL(:V_NAME IS NULL) AND :V_DID IS NULL AND :V_ID IS NULL))

   7 – access(“OBJECT_NAME”=:V_NAME)

   8 – filter((LNNVL(:V_DID IS NULL) AND :V_NAME IS NULL AND :V_ID IS NULL))

  10 – access(“DATA_OBJECT_ID”=:V_DID)

  11 – filter((LNNVL(:V_NAME IS NULL) AND LNNVL(:V_DID IS NULL) AND :V_ID IS NULL))

  12 – filter(“OBJECT_NAME”=:V_NAME)

  13 – access(“DATA_OBJECT_ID”=:V_DID)

  14 – filter((LNNVL(:V_ID IS NULL) AND :V_NAME IS NULL AND :V_DID IS NULL))

  16 – access(“OBJECT_ID”=:V_ID)

  17 – filter((LNNVL(:V_NAME IS NULL) AND LNNVL(:V_ID IS NULL) AND :V_DID IS NULL))

  18 – filter(“OBJECT_NAME”=:V_NAME)

  19 – access(“OBJECT_ID”=:V_ID)

  20 – filter((LNNVL(:V_DID IS NULL) AND LNNVL(:V_ID IS NULL) AND :V_NAME IS NULL))

  21 – filter(“DATA_OBJECT_ID”=:V_DID)

  22 – access(“OBJECT_ID”=:V_ID)

  23 – filter((LNNVL(:V_NAME IS NULL) AND LNNVL(:V_DID IS NULL) AND LNNVL(:V_ID IS NULL)))

  24 – filter((“OBJECT_NAME”=:V_NAME AND “DATA_OBJECT_ID”=:V_DID))

  25 – access(“OBJECT_ID”=:V_ID)

Hint Report (identified by operation id / Query Block Name / Object Alias):

Total hints for statement: 1

—————————————————————————

  23 –  SET$B2C621EA_8

           –  OR_EXPAND(@”SEL$1″ )

–//直接使用OR_EXPAND(@”SEL$1″ (1) (2) (3) (4) (5) (6) (7) (8)),执行计划变成全表扫描。

–//不再展开分析。

7.附上测试使用的脚本:

$ cat 10053x.sql

set term off

execute dbms_sqldiag.dump_trace(p_sql_id=>’&1′,p_child_number=>&2,p_component=>’Compiler’,p_file_id=>’a’||’&&1′);

set term on

set head off

@ t

set head on

define 1=&trc

$ cat tpt-oracle-master/t.sql

SELECT value tracefile FROM v$diag_info WHERE name = ‘Default Trace File’;

$ cat 10053y.sql

— Copyright 2023 lfree. All rights reserved.

— Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms and conditions.

————————————————————————————————————



— File name:   10053y.sql

— Purpose:     display Final query after transformations



— Author:      lfree



— Usage:

—     @ 10053y <trc_file>



———————————————————————————————————

SET TERM OFF

COLUMN trc_file  NEW_VALUE v_trc_file

–DEFINE trc_file = &1

SELECT NVL(‘&1′,’&TRC’) trc_file FROM DUAL ;

SELECT SUBSTR (‘&v_trc_file’, INSTR (‘&v_trc_file’, ‘/’, -1) + 1) trc_file FROM DUAL;

SET TERM ON

DEFINE trc_file = &v_trc_file

–DEFINE trc_file = &1

–COL trace_filename FOR A45

–COL adr_home FOR A45

–SELECT trace_filename, to_char(change_time, ‘dd-mm-yyyy hh24:mi:ss’) AS change_time, to_char(modify_time, ‘dd-mm-yyyy hh24:mi:ss’) AS modify_time, adr_home, con_id

–FROM gv$diag_trace_file

–WHERE lower(trace_filename) LIKE lower(‘%&v_trc_file%’)

–ORDER BY modify_time;

column trcline format a120

SELECT trcline

  FROM gv$diag_trace_file_contents

          MATCH_RECOGNIZE

          (

             PARTITION BY trace_filename

             ORDER BY line_number

             MEASURES payload AS trcline

             ALL ROWS PER MATCH

             PATTERN (a | b nc * | c | f n)

             DEFINE a AS (payload LIKE ‘qksptfSQM_GetTxt(): Anonymous Block%’)

            ,b AS (payload LIKE ‘qksptfSQM_GetTxt(): Macro Text%’)

            ,nc AS (payload NOT LIKE ‘qksptfSQM_Template(): Template Text%’)

            ,c AS (payload LIKE ‘qksptfSQM_Template(): Template Text%’)

            ,f AS (payload LIKE ‘Final query after%’)

          )

          x

 WHERE trace_filename = ‘&v_trc_file’;