[20250109]19c使用or_expand提示遇到的问题.txt

来源:这里教程网 时间:2026-03-03 21:17:33 作者:

[20250109]19c使用or_expand提示遇到的问题.txt --//生产系统使用19c,在使用or_expand提示时遇到的问题,在测试环境演示并做分析。 1.环境: 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.建立测试环境: SCOTT@book01p> create table t as select * from all_objects; Table created. SCOTT@book01p> create index i_t_object_id on t(object_id); Index created. --//分析略。 $ cat f3.txt set term off variable v_id number ; variable v_name varchar2(32) ; exec :v_id := 76191; exec :v_name := NULL; set term on select object_name,object_type from t  where ( ( :v_id = '' or :v_id is null) or t.object_id = :v_id) and ( ( :v_name = '' or :v_name is null) or t.object_name = :v_name) ; --//我们团队开发一种常见写法!! --//优化很简单,加入or_expand提示,复杂的话要加入Query Block Name。 $ cat f3a.txt set term off variable v_id number ; variable v_name varchar2(32) ; exec :v_id := 76191; exec :v_name := NULL; set term on select /*+ or_expand */ object_name,object_type from t  where ( ( :v_id = '' or :v_id is null) or t.object_id = :v_id) and ( ( :v_name = '' or :v_name is null) or t.object_name = :v_name) ; --//分别执行,记录各自的sql_id,然后使用spsw.sql脚本完成交换执行计划的outline。 SCOTT@book01p> @ spsw 32dn17b91frjg 0 1z3f571t20s0u 0 '' true PL/SQL procedure successfully completed. ================================================================================================================================================= if drop or alter sql profile ,run : execute dbms_sqltune.drop_sql_profile(name => 'switch tuning 1z3f571t20s0u') execute dbms_sqltune.alter_sql_profile(name => 'switch tuning 1z3f571t20s0u',attribute_name=>'STATUS',value=>'DISABLED') ================================================================================================================================================= 3.交换后测试: SCOTT@book01p> @ f3.txt OBJECT_NAME                    OBJECT_TYPE ------------------------------ ------------------------------ DEPT                           TABLE SCOTT@book01p> @ dpc '' outline '' PLAN_TABLE_OUTPUT ------------------------------------- SQL_ID  1z3f571t20s0u, child number 0 ------------------------------------- select object_name,object_type from t  where ( ( :v_id = '' or :v_id is null) or t.object_id = :v_id) and ( ( :v_name = '' or :v_name is null) or t.object_name = :v_name) Plan hash value: 1601196873 -------------------------------------------------------------------------------------------------------------------- | Id  | Operation         | Name | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | -------------------------------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT  |      |      1 |        |       |   412 (100)|          |      1 |00:00:00.01 |    1482 | |*  1 |  TABLE ACCESS FULL| T    |      1 |    175 |  8925 |   412   (1)| 00:00:01 |      1 |00:00:00.01 |    1482 | -------------------------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): -------------------------------------------------------------    1 - SEL$1 / "T"@"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" "T"@"SEL$1")       END_OUTLINE_DATA   */ Peeked Binds (identified by position): --------------------------------------    3 - (NUMBER, Primary=1)    6 - (VARCHAR2(30), CSID=852, Primary=4) Predicate Information (identified by operation id): ---------------------------------------------------    1 - filter(((:V_NAME IS NULL OR "T"."OBJECT_NAME"=:V_NAME) AND (:V_ID IS NULL OR "T"."OBJECT_ID"=:V_ID))) Hint Report (identified by operation id / Query Block Name / Object Alias): Total hints for statement: 8 (U - Unused (1), N - Unresolved (3)) ---------------------------------------------------------------------------    0 -  STATEMENT            -  ALL_ROWS            -  DB_VERSION('21.1.0')            -  IGNORE_OPTIM_EMBEDDED_HINTS            -  OPTIMIZER_FEATURES_ENABLE('21.1.0')    0 -  SET$2A13AF86_1          N -  FULL(@"SET$2A13AF86_1" "T"@"SET$2A13AF86_1")    0 -  SET$2A13AF86_2          N -  BATCH_TABLE_ACCESS_BY_ROWID(@"SET$2A13AF86_2" "T"@"SET$2A13AF86_2")          N -  INDEX_RS_ASC(@"SET$2A13AF86_2" "T"@"SET$2A13AF86_2" ("T"."OBJECT_ID"))    1 -  SEL$1          U -  OR_EXPAND(@"SEL$1" (1) (2)) Note -----    - SQL profile switch tuning 1z3f571t20s0u used for this statement --//可以发现并没有使用交换的执行计划,提示U -  OR_EXPAND(@"SEL$1" (1) (2))。 --//我看了以前sql profile脚本失效的相关笔记,遇到这类情况选择sql patch简单一些。 SYS@book01p> execute dbms_sqltune.drop_sql_profile(name => 'switch tuning 1z3f571t20s0u') PL/SQL procedure successfully completed. SYS@book01p> @ sqlpatch 1z3f571t20s0u 'OR_EXPAND(@"SEL$1" )' input @sqlpatch sqlid 'hint_text' oracle_version(11 or 12) drop sql patch ,run  exec sys.dbms_sqldiag.drop_sql_patch('sqlpatch_1z3f571t20s0u'); display sql path message , run @spext 1z3f571t20s0u PL/SQL procedure successfully completed. --//以sys用户执行 --//注:尝试使用@ sqlpatch 1z3f571t20s0u 'OR_EXPAND(@"SEL$1" (1) (2) )'不行。 SCOTT@book01p> @ f3.txt OBJECT_NAME                    OBJECT_TYPE ------------------------------ ------------------------------ DEPT                           TABLE SCOTT@book01p> @ dpc '' '' '' PLAN_TABLE_OUTPUT ------------------------------------- SQL_ID  1z3f571t20s0u, child number 0 ------------------------------------- select object_name,object_type from t  where ( ( :v_id = '' or :v_id is null) or t.object_id = :v_id) and ( ( :v_name = '' or :v_name is null) or t.object_name = :v_name) Plan hash value: 2282446254 ---------------------------------------------------------------------------------------------------------------------------------------------------- | 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 |       4 | |   1 |  VIEW                                  | VW_ORE_1B35BA0F |      1 |   3500 |   270K|   414   (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                  | T               |      0 |   3499 |   157K|   412   (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| T               |      1 |      1 |    51 |     2   (0)| 00:00:01 |      1 |00:00:00.01 |       4 | |*  7 |      INDEX RANGE SCAN                  | I_T_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_1B35BA0F"@"SEL$1B35BA0F"    2 - SET$2A13AF86    3 - SET$2A13AF86_1    4 - SET$2A13AF86_1 / "T"@"SET$2A13AF86_1"    5 - SET$2A13AF86_2    6 - SET$2A13AF86_2 / "T"@"SET$2A13AF86_2"    7 - SET$2A13AF86_2 / "T"@"SET$2A13AF86_2" Peeked Binds (identified by position): --------------------------------------    3 - (NUMBER, Primary=1)    6 - (VARCHAR2(30), CSID=852, Primary=4) Predicate Information (identified by operation id): ---------------------------------------------------    3 - filter(:V_ID IS NULL)    4 - filter((:V_NAME IS NULL OR "T"."OBJECT_NAME"=:V_NAME))    5 - filter(LNNVL(:V_ID IS NULL))    6 - filter((:V_NAME IS NULL OR "T"."OBJECT_NAME"=:V_NAME))    7 - access("T"."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" ) Note -----    - SQL patch "sqlpatch_1z3f571t20s0u" used for this statement 4.继续: --//正常情况下object_name字段应该有索引,这里不用,也许其他sql语句要使用,建立object_name索引看看。 SCOTT@book01p> create index i_t_object_name on t(object_name); Index created. SCOTT@book01p> @ f3.txt OBJECT_NAME                    OBJECT_TYPE ------------------------------ ------------------------------ DEPT                           TABLE SCOTT@book01p> @ dpc '' outline '' PLAN_TABLE_OUTPUT ------------------------------------- SQL_ID  1z3f571t20s0u, child number 0 ------------------------------------- select object_name,object_type from t  where ( ( :v_id = '' or :v_id is null) or t.object_id = :v_id) and ( ( :v_name = '' or :v_name is null) or t.object_name = :v_name) Plan hash value: 3783172993 ---------------------------------------------------------------------------------------------------------------------------------------------------- | Id  | Operation                              | Name            | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers | ---------------------------------------------------------------------------------------------------------------------------------------------------- |   0 | SELECT STATEMENT                       |                 |      1 |        |       |   418 (100)|          |      1 |00:00:00.01 |       4 | |   1 |  VIEW                                  | VW_ORE_1B35BA0F |      1 |  69985 |  5399K|   418   (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                  | T               |      0 |  69982 |  3143K|   412   (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| T               |      0 |      1 |    46 |     2   (0)| 00:00:01 |      0 |00:00:00.01 |       0 | |*  7 |      INDEX RANGE SCAN                  | I_T_OBJECT_NAME |      0 |      1 |       |     2   (0)| 00:00:01 |      0 |00:00:00.01 |       0 | |*  8 |    FILTER                              |                 |      1 |        |       |            |          |      1 |00:00:00.01 |       4 | |   9 |     TABLE ACCESS BY INDEX ROWID BATCHED| T               |      1 |      1 |    51 |     2   (0)| 00:00:01 |      1 |00:00:00.01 |       4 | |* 10 |      INDEX RANGE SCAN                  | I_T_OBJECT_ID   |      1 |      1 |       |     1   (0)| 00:00:01 |      1 |00:00:00.01 |       3 | |* 11 |    FILTER                              |                 |      1 |        |       |            |          |      0 |00:00:00.01 |       0 | |* 12 |     TABLE ACCESS BY INDEX ROWID BATCHED| T               |      0 |      1 |    51 |     2   (0)| 00:00:01 |      0 |00:00:00.01 |       0 | |* 13 |      INDEX RANGE SCAN                  | I_T_OBJECT_NAME |      0 |      1 |       |     2   (0)| 00:00:01 |      0 |00:00:00.01 |       0 | ---------------------------------------------------------------------------------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): -------------------------------------------------------------    1 - SET$171C43EC   / "VW_ORE_1B35BA0F"@"SEL$1B35BA0F"    2 - SET$171C43EC    3 - SET$171C43EC_1    4 - SET$171C43EC_1 / "T"@"SET$171C43EC_1"    5 - SET$171C43EC_2    6 - SET$171C43EC_2 / "T"@"SET$171C43EC_2"    7 - SET$171C43EC_2 / "T"@"SET$171C43EC_2"    8 - SET$171C43EC_3    9 - SET$171C43EC_3 / "T"@"SET$171C43EC_3"   10 - SET$171C43EC_3 / "T"@"SET$171C43EC_3"   11 - SET$171C43EC_4   12 - SET$171C43EC_4 / "T"@"SET$171C43EC_4"   13 - SET$171C43EC_4 / "T"@"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_1B35BA0F"@"SEL$1B35BA0F")       FULL(@"SET$171C43EC_1" "T"@"SET$171C43EC_1")       INDEX_RS_ASC(@"SET$171C43EC_2" "T"@"SET$171C43EC_2" ("T"."OBJECT_NAME"))       BATCH_TABLE_ACCESS_BY_ROWID(@"SET$171C43EC_2" "T"@"SET$171C43EC_2")       INDEX_RS_ASC(@"SET$171C43EC_3" "T"@"SET$171C43EC_3" ("T"."OBJECT_ID"))       BATCH_TABLE_ACCESS_BY_ROWID(@"SET$171C43EC_3" "T"@"SET$171C43EC_3")       INDEX_RS_ASC(@"SET$171C43EC_4" "T"@"SET$171C43EC_4" ("T"."OBJECT_NAME"))       BATCH_TABLE_ACCESS_BY_ROWID(@"SET$171C43EC_4" "T"@"SET$171C43EC_4")       END_OUTLINE_DATA   */ Peeked Binds (identified by position): --------------------------------------    3 - (NUMBER, Primary=1)    6 - (VARCHAR2(30), CSID=852, Primary=4) Predicate Information (identified by operation id): ---------------------------------------------------    3 - filter((:V_NAME IS NULL AND :V_ID IS NULL))    5 - filter((LNNVL(:V_NAME IS NULL) AND :V_ID IS NULL))    7 - access("T"."OBJECT_NAME"=:V_NAME)    8 - filter((LNNVL(:V_ID IS NULL) AND :V_NAME IS NULL))   10 - access("T"."OBJECT_ID"=:V_ID)   11 - filter((LNNVL(:V_NAME IS NULL) AND LNNVL(:V_ID IS NULL)))   12 - filter("T"."OBJECT_ID"=:V_ID)   13 - access("T"."OBJECT_NAME"=:V_NAME) Hint Report (identified by operation id / Query Block Name / Object Alias): Total hints for statement: 1 ---------------------------------------------------------------------------   11 -  SET$171C43EC_4            -  OR_EXPAND(@"SEL$1" ) Note -----    - SQL patch "sqlpatch_1z3f571t20s0u" used for this statement 101 rows selected. --//outline记录的是      OR_EXPAND(@"SEL$1" (1) (2) (3) (4)) --//视乎这样的情况oracle使用or_expand更加智能,完美的展开各种条件,可惜无法在11.2.0.4上使用,11g只能使用use_concat. --//现在有点明白为什么使用我写的spsw.sql交换执行计划不行,因为这部分内容会变化,只能使用sql patch方式稳定执行计划。 5.附上测试使用的sqlpatch.sql脚本: $ cat sqlpatch.sql prompt prompt input @sqlpatch sqlid 'hint_text' oracle_version(11 or 12) prompt drop sql patch ,run  exec sys.dbms_sqldiag.drop_sql_patch('sqlpatch_&1');; prompt display sql path message , run @spext &1 define noprint='noprint' set term off col tpt_version_old  &noprint new_value _tpt_version_old col tpt_version_new  &noprint new_value _tpt_version_new col tpt_noprint      &noprint new_value _tpt_noprint WITH version AS (SELECT TO_NUMBER (SUBSTR (version, 1, 2)) v FROM v$instance) SELECT CASE WHEN v <= 11 THEN '' ELSE '--' END tpt_version_old       ,CASE WHEN v > 11  THEN '' ELSE '--' END tpt_version_new   FROM version; set term on declare    v_sql CLOB;    patch_name   VARCHAR2 (100); begin    select sql_fulltext into v_sql from gv$sqlarea where sql_id='&1' and rownum=1; --  select sql_text into v_sql from DBA_HIST_SQLTEXT where sql_id='&1' and rownum=1; &&_tpt_version_old   sys.dbms_sqldiag_internal.i_create_patch( &&_tpt_version_old      sql_text  => v_sql, &&_tpt_version_old      hint_text => '&2', &&_tpt_version_old      name      => 'sqlpatch_&1'); &&_tpt_version_new   patch_name := &&_tpt_version_new       sys.DBMS_SQLDIAG.create_sql_patch &&_tpt_version_new       ( &&_tpt_version_new          sql_text    => v_sql &&_tpt_version_new         ,hint_text   => '&2' &&_tpt_version_new         ,name        => 'sqlpatch_&1' &&_tpt_version_new       ); end; /

相关推荐