固定执行计划-手工指定PLAN OUTLINE

联系:QQ(5163721)

标题:固定执行计划-手工指定PLAN OUTLINE

作者:Lunar©版权所有[文章允许转载,但必须以链接方式注明源地址,否则追究法律责任.]

测试目的: hint和手工指定OUTLINE参数的方式来帮顶执行计划,谁的优先级高?
.
固定执行计划-使用SQL Tuning Advisor
固定执行计划-手工指定PLAN OUTLINE
固定执行计划-手工指定索引名称的方式
固定执行计划-使用coe_xfr_sql_profile固定执行计划
固定执行计划-使用SPM(Sql Plan Management)固定执行计划
.
由于上一个测试中,已经绑定了sql使用SQL Tuning Advisor中的执行计划,从而使SQL走索引了(覆盖了hint)。这里我们需要先删除该SQL Profile,再手工绑定试试。
确认下SQL PROFILE的内容:

LUNAR@lunardb>SELECT * FROM DBA_SQL_PROFILES;

NAME                           CATEGORY                              SIGNATURE
------------------------------ ------------------------------ ----------------
SQL_TEXT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CREATED                                                                     LAST_MODIFIED
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
DESCRIPTION
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TYPE    STATUS   FOR          TASK_ID TASK_EXEC_NAME                      TASK_OBJ_ID      TASK_FND_ID      TASK_REC_ID
------- -------- --- ---------------- ------------------------------ ---------------- ---------------- ----------------
SYS_SQLPROF_015236655fb80000   DEFAULT                        6.5941520220E+17
select /*+ no_index(lunartest1 idx_lunartest1_n) */ * from lunartest1 where n=1
12-JAN-16 10.12.39.000000 AM                                                12-JAN-16 10.12.39.000000 AM

MANUAL  ENABLED  NO               158 EXEC_146                                      1                1                1


Elapsed: 00:00:00.02
LUNAR@lunardb>
LUNAR@lunardb>SELECT extractValue(value(h),'.') AS hint
  2  FROM sys.sqlobj$data od, sys.sqlobj$ so,
  3  table(xmlsequence(extract(xmltype(od.comp_data),'/outline_data/hint'))) h
  4  WHERE so.name = 'SYS_SQLPROF_015236655fb80000'
  5  AND so.signature = od.signature
  6  AND so.category = od.category
  7  AND so.obj_type = od.obj_type
  8  AND so.plan_id = od.plan_id;

HINT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
COLUMN_STATS("LUNAR"."LUNARTEST1", "N", scale, length=3 distinct=10000 nulls=0 min=1 max=10000)
TABLE_STATS("LUNAR"."LUNARTEST1", scale, blocks=20 rows=10000)
OPTIMIZER_FEATURES_ENABLE(default)
IGNORE_OPTIM_EMBEDDED_HINTS

Elapsed: 00:00:00.05
LUNAR@lunardb>

这里我们看到该SQP Profile中提供了详细的表和列的统计信息
并且有“IGNORE_OPTIM_EMBEDDED_HINTS”,也就是忽略嵌入到SQL中的hint
确认一下,当前SQL语句使用了该SQL Profile:

LUNAR@lunardb>select * from table(dbms_xplan.display_cursor('bjgduva68mbqm',null,'outline'));

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  bjgduva68mbqm, child number 0
-------------------------------------
select /*+ no_index(lunartest1 idx_lunartest1_n) */ * from lunartest1
where n=1

Plan hash value: 3241900148

-------------------------------------------------------------------------------------
| Id  | Operation        | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |                  |       |       |     1 (100)|          |
|*  1 |  INDEX RANGE SCAN| IDX_LUNARTEST1_N |     1 |     3 |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.4')
      DB_VERSION('11.2.0.4')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      INDEX(@"SEL$1" "LUNARTEST1"@"SEL$1" ("LUNARTEST1"."N"))
      END_OUTLINE_DATA
  */

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

   1 - access("N"=1)

Note
-----
   - SQL profile SYS_SQLPROF_015236655fb80000 used for this statement


37 rows selected.

Elapsed: 00:00:00.23
LUNAR@lunardb>

这里我们看到,当前执行确实使用了SQL profile SYS_SQLPROF_015236655fb80000,因此hint no_index失效了
(优先级低于SYS_SQLPROF_015236655fb80000,具体参见固定执行计划-使用SQL Tuning Advisor
查看SYS_SQLPROF_015236655fb80000的OUTLINE信息:

LUNAR@lunardb>select '''' || extractvalue(value(d), '/hint') || ''',' as outline_hints
  2  from xmltable('/*/outline_data/hint' passing (
  3                                     select xmltype(other_xml) as xmlval
  4                                     from v$sql_plan 
  5                                     where sql_id = 'bjgduva68mbqm' and plan_hash_value = '3241900148' and other_xml is not null
  6                                     )
  7             ) d;

OUTLINE_HINTS
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
'IGNORE_OPTIM_EMBEDDED_HINTS',
'OPTIMIZER_FEATURES_ENABLE('11.2.0.4')',
'DB_VERSION('11.2.0.4')',
'ALL_ROWS',
'OUTLINE_LEAF(@"SEL$1")',
'INDEX(@"SEL$1" "LUNARTEST1"@"SEL$1" ("LUNARTEST1"."N"))',

6 rows selected.

Elapsed: 00:00:00.06
LUNAR@lunardb>

这里我们看到该SQP Profile中提供了详细的表和列的统计信息
并且有“IGNORE_OPTIM_EMBEDDED_HINTS”,也就是忽略嵌入到SQL中的hint
现在,我们删除这个SQL Profile,稍后使用上面的OUTLINE手工绑定执行计划:

LUNAR@lunardb>begin
  2     DBMS_SQLTUNE.DROP_SQL_PROFILE(name => 'SYS_SQLPROF_015236655fb80000');
  3  end;
  4  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.02
LUNAR@lunardb>SELECT * FROM DBA_SQL_PROFILES;

no rows selected

Elapsed: 00:00:00.00
LUNAR@lunardb>

此时,应该正常按照hint走了全表扫描:

LUNAR@lunardb>set autotrace traceonly exp stat
LUNAR@lunardb>select /*+ no_index(lunartest1 idx_lunartest1_n) */ * from lunartest1 where n=1;

Elapsed: 00:00:00.03

Execution Plan
----------------------------------------------------------
Plan hash value: 1172089107

--------------------------------------------------------------------------------
| Id  | Operation         | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |            |     1 |     4 |     7   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| LUNARTEST1 |     1 |     4 |     7   (0)| 00:00:01 |
--------------------------------------------------------------------------------

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

   1 - filter("N"=1)


Statistics
----------------------------------------------------------
        114  recursive calls
          0  db block gets
        137  consistent gets
          0  physical reads
          0  redo size
        519  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
         15  sorts (memory)
          0  sorts (disk)
          1  rows processed

LUNAR@lunardb>

手工指定sqlprofile参数的方式绑定执行计划:

LUNAR@lunardb>declare
  2     v_hints sys.sqlprof_attr;
  3     sql_txt clob;
  4  begin 
  5     v_hints:=sys.sqlprof_attr(
  6           'BEGIN_OUTLINE_DATA',
  7           'IGNORE_OPTIM_EMBEDDED_HINTS',
  8           'OPTIMIZER_FEATURES_ENABLE(''11.2.0.4'')',
  9           'DB_VERSION(''11.2.0.4'')',
 10           'ALL_ROWS',
 11           'OUTLINE_LEAF(@"SEL$1")',
 12           'INDEX(@"SEL$1" "LUNARTEST1"@"SEL$1" ("LUNARTEST1"."N"))',
 13           'END_OUTLINE_DATA'
 14     );
 15  
 16     select sql_fulltext into sql_txt from v$sql where sql_id='&sqlid';
 17     dbms_sqltune.import_sql_profile(sql_text => sql_txt,
 18             profile => v_hints,name => 'Lunar_Manaual_sqlprofile',
 19             replace => TRUE,force_match => TRUE);
 20  end;
 21  /
Enter value for sqlid: bjgduva68mbqm
old  16:        select sql_fulltext into sql_txt from v$sql where sql_id='&sqlid';
new  16:        select sql_fulltext into sql_txt from v$sql where sql_id='bjgduva68mbqm';

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.53
LUNAR@lunardb>
LUNAR@lunardb>SELECT * FROM DBA_SQL_PROFILES;

NAME                           CATEGORY                              SIGNATURE
------------------------------ ------------------------------ ----------------
SQL_TEXT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CREATED                                                                     LAST_MODIFIED
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
DESCRIPTION
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TYPE    STATUS   FOR          TASK_ID TASK_EXEC_NAME                      TASK_OBJ_ID      TASK_FND_ID      TASK_REC_ID
------- -------- --- ---------------- ------------------------------ ---------------- ---------------- ----------------
Lunar_Manaual_sqlprofile       DEFAULT                        9.9008162990E+18
select /*+ no_index(lunartest1 idx_lunartest1_n) */ * from lunartest1 where n=1
12-JAN-16 10.44.30.000000 AM                                                12-JAN-16 10.44.30.000000 AM

MANUAL  ENABLED  YES


Elapsed: 00:00:00.02
LUNAR@lunardb>

再次查询,看看Lunar_Manaual_sqlprofile是否生效:

LUNAR@lunardb>select /*+ no_index(lunartest1 idx_lunartest1_n) */ * from lunartest1 where n=1;

Elapsed: 00:00:00.02

Execution Plan
----------------------------------------------------------
Plan hash value: 3241900148

-------------------------------------------------------------------------------------
| Id  | Operation        | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |                  |     1 |     4 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| IDX_LUNARTEST1_N |     1 |     4 |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

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

   1 - access("N"=1)

Note
-----
   - SQL profile "Lunar_Manaual_sqlprofile" used for this statement


Statistics
----------------------------------------------------------
         34  recursive calls
          0  db block gets
         13  consistent gets
          1  physical reads
          0  redo size
        519  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed

LUNAR@lunardb>

这里我们看到Lunar_Manaual_sqlprofile已经生效,且sql语句虽然带有no_index的hint,但是仍然可以按照SQL Profile指定的大纲使用索引
总结:
这里虽然有hint指定了no index,但是sql语句仍然按照Lunar_Manaual_sqlprofile指定的profile使用了index的
说明,使用手工指定outline参数的方式绑定的执行计划优先级高于hint

此条目发表在 Performence Tuning 分类目录,贴了 标签。将固定链接加入收藏夹。

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注