当前位置:  数据库>oracle

Oracle固定SQL的执行计划(二)---SPM

    来源: 互联网  发布时间:2017-06-27

    本文导语: 之前写了一篇文章介绍的是,即使无法修改目标SQL的SQL文本。但SQL Profile实际上只是一种亡羊补牢、被动的技术手段,应用在那些执行计划已经发生了不好的变更的SQL上,即当我们发现这些SQL的执行计划已经出了问题时通过创建S...

之前写了一篇文章介绍的是,即使无法修改目标SQL的SQL文本。但SQL Profile实际上只是一种亡羊补牢、被动的技术手段,应用在那些执行计划已经发生了不好的变更的SQL上,即当我们发现这些SQL的执行计划已经出了问题时通过创建SQL Profile来纠正、稳定这些SQL的执行计划。即便通过创建SQL Profile解决了目标SQL执行计划变更的问题,依然不能保证系统后续执行的SQL的执行计划就不再发生不好的变更。这种不确定性会给Oracle数据库大版本升级(比如从Oracle 10g升级到Oracle 11g)带来一系列的麻烦,因为不清楚升级之后原先系统中哪些SQL的执行计划会发生不好的变更。

为了解决上述问题,Oracle在11g中推出了SPM(SQL Plan Management)。SPM是一种主动的稳定执行计划的手段,能够保证只有被验证过的执行计划才会被启用,当由于种种原因(如统计信息的变更)而导致目标SQL产生了新的执行计划后,这个新的执行计划并不会被马上启用,直到它已经被我们验证过其执行效率会比原先执行计划高才会被启用。

随着Oracle数据库版本的不段推进,其CBO的算法、功能也在一直不断进化和增加,所以同样的SQL有可能在新版本的Oralce数据库中执行效率更高,如果我们使用了SQL Profile(特别是使用了Manual类型的SQL Profile)来稳定目标SQL的执行计划,那就意味着可能失去了继续优化上述SQL的执行效率的机会。而SPM的推出可以说彻底解决了执行计划稳定性的问题,它既能主动地稳定执行计划,又保留了继续使用新的执行效率可能更高的执行计划的机会。

当启用了SPM后,每一个SQL都会存在对应的SQL Plan Baseline,这个SQL Plan Baseline里存储的就是该SQL的执行计划,如果一个SQL有多个执行计划,那么该SQL就可能会有多个SQL Plan Baseline,可以从DBA_SQL_PLAN_BASELINES中查看目标SQL所有的SQL Plan Baseline。

DBA_SQL_PLAN_BASELINES中的列ENABLED和ACCEPTED用来描述一个SQL Plan Baseline所对应的执行计划是否能被Oracle启用,只有ENABLED和ACCEPTED的值均为“YES”的SQL Plan Baseline所对应的执行计划才会被Oracle启用,如果一具SQL有超过1个以上的SQL Plan Baseline的ENABLED和ACCEPTED的值均为YES,则Oracle会从中选择成本值最小的一个所对应的执行坟墓来作为该SQL的执行计划。

在Oracle 11g及其以上的版本中,有如下两种方法可以产生目标SQL的SQL Plan Baseline。

  • 自动捕获
  • 手工生成/批量导入(批量导入尤其适用于Oracle数据库大版本的升级,它可以确保升级后原有系统所胡SQL的执行计划不会发生变化)

下面分别介绍如何自动捕获和手工的方式来产生SQL Plan Baseline。

1 自动捕获SQL Plan Baseline

参数OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES用于控制是否开启自动捕获SQL Plan Baseline,其默认值为FALSE,表示在默认情况下,Oracle并不会自动捕获SQL Plan Baseline。这个参数可以在session或系统级别动态修改。当修改为TRUE后,则Oracle会对上述参数影响范围内所有重复执行的SQL自动捕获其SQL Plan Baseline,并且针对目标SQL第一次捕获的SQL Plan Baseline的ENABLED和ACCEPTED的值均为“YES”。随后如果该SQL的执行计划发生了变更,则再次捕获到的SQL Plan Baseline的ENABLED的值依然为YES,但ACCEPTED的值变为了NO,这表示后续变更的执行计划虽然被捕获了,但Oracle不会将其作为该SQL的执行计划来执行,即此时Oracle会永远沿用该SQL第一次被捕获的SQL Plan Baseline所对应的执行计划(除非后续做了手工调整)。

参数OPTIMIZER_USE_SQL_PLAN_BASELINES用于控制是否启用SQL Plan Baseline,其默认值为TRUE,表示在默认情况下,Oracle在生成执行计划时就会启用SPM,使用已有的SQL Plan Baseline,这个参数也可以在session或系统级别动态修改。

下面看一下实例:

查看上述两个参数的默认值

zx@MYDB>show parameter sql_plan
 
NAME                                 TYPE                              VALUE
------------------------------------ --------------------------------- ------------------------------
optimizer_capture_sql_plan_baselines boolean                           FALSE
optimizer_use_sql_plan_baselines     boolean                           TRUE

在当前session中禁掉SPM并同时开启自动捕获SQL Plan Baseline:

zx@MYDB>alter session set optimizer_use_sql_plan_baselines=FALSE;
 
Session altered.
 
zx@MYDB>alter session set optimizer_capture_sql_plan_baselines=TRUE;
 
Session altered.

创建测试表T2

zx@MYDB>create table t2 as select * from dba_objects;
 
Table created.
 
zx@MYDB>create index idx_t2 on t2(object_id);
 
Index created.
 
zx@MYDB>exec dbms_stats.gather_table_stats(ownname=>USER,tabname=>'T2',estimate_percent=>100,cascade=>true);
 
PL/SQL procedure successfully completed.
 
zx@MYDB>select object_id,object_name from t2 where object_id between 103 and 108;
 
 OBJECT_ID OBJECT_NAME
---------- ------------------------------
       103 MIGRATE$
       104 DEPENDENCY$
       105 ACCESS$
       106 I_DEPENDENCY1
       107 I_DEPENDENCY2
       108 I_ACCESS1
 
6 rows selected.

从执行计划上看,走的是索引IDX_T2上的索引范围扫描,因为SQL只执行了一次,所以Oracle不会自动捕获SQL Plan Baseline,DBA_SQL_PLAN_BASELINES中没有记录

zx@MYDB>col sql_handle for a30
zx@MYDB>col plan_name for a30
zx@MYDB>col origin for a20
zx@MYDB>col sql_text for a70
zx@MYDB>select sql_handle,plan_name,origin,enabled,accepted,sql_text from dba_sql_plan_baselines;
 
no rows selected

再次执行上述SQL,因为重复执行该SQL,Oracle自动捕获了这个SQL的SQL Plan Baseline 

zx@MYDB>select object_id,object_name from t2 where object_id between 103 and 108;
 
 OBJECT_ID OBJECT_NAME
---------- ------------------------------
       103 MIGRATE$
       104 DEPENDENCY$
       105 ACCESS$
       106 I_DEPENDENCY1
       107 I_DEPENDENCY2
       108 I_ACCESS1
 
6 rows selected.
 
zx@MYDB>select sql_handle,plan_name,origin,enabled,accepted,sql_text from dba_sql_plan_baselines;
 
SQL_HANDLE                     PLAN_NAME                      ORIGIN                ENABLED   ACCEPTED  SQL_TEXT
------------------------------ ------------------------------ -------------------- --------- --------- ------------------------------------------------------------
SYS_SQL_ac526b1e4be74880       SQL_PLAN_asnmb3t5yfk4024c6dbb6 AUTO-CAPTURE          YES       YES       select object_id,object_name from t2 where object_id between 103 and 108

现在将索引IDX_T2的聚簇因子修改为2400万,目的是为了能让SQL的执行计划变为对表T2的全表扫描(为何修改聚簇因子,参考 )。修改完后再执行上述SQL,并查看执行计划:

zx@MYDB>exec dbms_stats.set_index_stats(ownname=>USER,indname=>'IDX_T2',clstfct=>24000000,no_invalidate=>false);
 
PL/SQL procedure successfully completed.
 
zx@MYDB>select index_name,clustering_factor from dba_indexes where index_name='IDX_T2';
 
INDEX_NAME                                                                                 CLUSTERING_FACTOR
------------------------------------------------------------------------------------------ -----------------
IDX_T2                                                                                              24000000
 
zx@MYDB>select object_id,object_name from t2 where object_id between 103 and 108;
 
 OBJECT_ID OBJECT_NAME
---------- ------------------------------
       103 MIGRATE$
       104 DEPENDENCY$
       105 ACCESS$
       106 I_DEPENDENCY1
       107 I_DEPENDENCY2
       108 I_ACCESS1
 
6 rows selected.

从执行计划中可以看出该SQL的执行计划已经变为全表扫描。因为目标SQL已经重复执行且同时又产生了一个新的执行计划,所以现在Oracle就会自动捕获并创建这个新的执行计划所对应的SQL Plan Baseline了。从如下查询可以看出Oracle对新的执行计划产生了一个新的SQL Plan Baseline,其ENABLED的值依然为YES,但ACCEPTED的值变为了NO:

现在我们对当前Session关闭自动捕获SQL Plan Baseline并同时开启SPM,现在索引IDX_T2的聚簇因子依然为2400万,再次执行目标SQL,并查看执行计划:

zx@MYDB>alter session set optimizer_use_sql_plan_baselines=TRUE;
 
Session altered.
 
zx@MYDB>alter session set optimizer_capture_sql_plan_baselines=FALSE;
 
Session altered.
 
 
zx@MYDB>select index_name,clustering_factor from dba_indexes where index_name='IDX_T2';
 
INDEX_NAME                                                                                 CLUSTERING_FACTOR
------------------------------------------------------------------------------------------ -----------------
IDX_T2                                                                                              24000000
 
zx@MYDB>select object_id,object_name from t2 where object_id between 103 and 108;
 
 OBJECT_ID OBJECT_NAME
---------- ------------------------------
       103 MIGRATE$
       104 DEPENDENCY$
       105 ACCESS$
       106 I_DEPENDENCY1
       107 I_DEPENDENCY2
       108 I_ACCESS1
 
6 rows selected.

从上面的显示内容可以看出,现在目标SQL的执行又从全表扫描恢复为了索引范围扫描,并且执行计划中的Note部分有“SQL plan baseline SQL_PLAN_asnmb3t5yfk4024c6dbb6 used for this statement”内容,说明SPM开启的情况下,即便目标SQL产生了新的执行计划,Oracle依然只会应用该SQL的ENABLED和ACCEPTED的值均为YES的SQL Plan Baselline。

如果想启用目标SQL新的执行计划(即全表扫描),应该如何做呢?

针对不同的Oracle版本,会有不同的处理方法。比如这里想启用目标SQL的新的执行计划,如果是11gR1的环境,则只需要将目标SQL所采用的名为SQL_PLAN_asnmb3t5yfk4024c6dbb6的SQL Plan Baseline(即索引范围扫描)的ACCEPTED的值设为NO就可以了。但对于11gR2环境,上述方法会报错,因为在11gR2中,所有已经被ACCEPTED的SQL Plan Baseline的ACCEPTED的值将不再能够被设为NO:

zx@MYDB>var temp varchar2(1000);
zx@MYDB>exec :temp := dbms_spm.alter_sql_plan_baseline(sql_handle=>'SYS_SQL_ac526b1e4be74880',plan_name=>'SQL_PLAN_asnmb3t5yfk4024c6dbb6',attribute_name=>'accepted',attribute_value=>'NO');
BEGIN :temp := dbms_spm.alter_sql_plan_baseline(sql_handle=>'SYS_SQL_ac526b1e4be74880',plan_name=>'SQL_PLAN_asnmb3t5yfk4024c6dbb6',attribute_name=>'accepted',attribute_value=>'NO'); END;
 
*
ERROR at line 1:
ORA-38136: invalid attribute name ACCEPTED specified
ORA-06512: at "SYS.DBMS_SPM", line 2469
ORA-06512: at line 1

在11gR2中,我们可以联合使用DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE和DBMS_SPM.ALTER_SQL_PLAN_BASELINE达到启用目标SQL新的执行计划的目的。

先用DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE将新的执行计划(全表扫描)所对应的SQL Plan Baseline的ACCEPTED值设为“YES”:

zx@MYDB>exec :temp := dbms_spm.evolve_sql_plan_baseline(sql_handle=>'SYS_SQL_ac526b1e4be74880',plan_name=>'SQL_PLAN_asnmb3t5yfk40b860bcf2',verify=>'NO',commit=>'YES');
 
PL/SQL procedure successfully completed.

从上面显示的内容看到如下信息:“Plan: SQL_PLAN_asnmb3t5yfk40b860bcf2----Plan was changed to an accepted plan.”,这表明已经将新的执行计划(全表扫描)所对应的SQL Plan Baseline的ACCEPTED值设为YES

从下面的查询结果也可以证明:

zx@MYDB>select sql_handle,plan_name,origin,enabled,accepted,sql_text from dba_sql_plan_baselines where sql_text like 'select object_id%';
 
SQL_HANDLE             PLAN_NAME          ORIGIN         ENABLED   ACCEPTED  SQL_TEXT
------------------------------ ------------------------------ -------------------- --------- --------- ----------------------------------------------------------------------
SYS_SQL_ac526b1e4be74880       SQL_PLAN_asnmb3t5yfk4024c6dbb6 AUTO-CAPTURE     YES       YES       select object_id,object_name from t2 where object_id between 103 and 108
 
 
SYS_SQL_ac526b1e4be74880       SQL_PLAN_asnmb3t5yfk40b860bcf2 AUTO-CAPTURE     YES       YES       select object_id,object_name from t2 where object_id between 103 and 108

然后再使用DBMS_SPM.ALTER_SQL_PLAN_BASELINE将原先的执行计划(索引范围扫描)对应的SQL Plan Baseline的ENABLED的值设为NO:

zx@MYDB>exec :temp := dbms_spm.alter_sql_plan_baseline(sql_handle=>'SYS_SQL_ac526b1e4be74880',plan_name=>'SQL_PLAN_asnmb3t5yfk4024c6dbb6',attribute_name=>'enabled',attribute_value=>'NO');
 
PL/SQL procedure successfully completed.
 
zx@MYDB>select sql_handle,plan_name,origin,enabled,accepted,sql_text from dba_sql_plan_baselines where sql_text like 'select object_id%';
 
SQL_HANDLE             PLAN_NAME          ORIGIN         ENABLED   ACCEPTED  SQL_TEXT
------------------------------ ------------------------------ -------------------- --------- --------- ----------------------------------------------------------------------
SYS_SQL_ac526b1e4be74880       SQL_PLAN_asnmb3t5yfk4024c6dbb6 AUTO-CAPTURE     NO         YES       select object_id,object_name from t2 where object_id between 103 and 108
 
 
SYS_SQL_ac526b1e4be74880       SQL_PLAN_asnmb3t5yfk40b860bcf2 AUTO-CAPTURE     YES       YES       select object_id,object_name from t2 where object_id between 103 and 108

再次执行目标SQL

zx@MYDB>select object_id,object_name from t2 where object_id between 103 and 108;
 
 OBJECT_ID OBJECT_NAME
---------- ------------------------------
       103 MIGRATE$
       104 DEPENDENCY$
       105 ACCESS$
       106 I_DEPENDENCY1
       107 I_DEPENDENCY2
       108 I_ACCESS1
 
6 rows selected.

从上述显示可以看出,现在SQL的执行计划已经变为了全表扫描,我们要启用新的执行计划(全表扫描)的目的已经实现,Note部分也有了提示。

从上述测试结果可以看出,实际上我们可以轻易地在目标SQL的多个执行计划中切换,所以SPM确实是既能够主动地稳定执行计划,又保留了继续使用新的执行计划的机会,并且我们很容易就能启用新的执行计划。

下面介绍手工生成SQL Plan Baseline:

手工生成目标SQL的SQL Plan Baseline其实非常简单,其核心就是调用DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE。这里只讨论针对单个SQL的SQL Plan Baseline的手工生成。

之前介绍过用Manual类型的SQL Profile可以在不改变目标SQL的SQL文本的情况下调整其执行计划。实际上,用手工生成SQL Plan Baseline的方式也完全可以实现同样的目的,甚至会比使用Manual类型的SQL Profile更加简洁。

手工生成目标SQL的SQL Plan Baseline的具体步骤为:

1)针对目标SQL使用DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE手工生成其初始执行计划所对应的SQL Plan Baseline。此时,使用DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE传入的参数如���所示:

dbms_spm.load_plans_from_cursor_cache(sql_id=>'原目标SQL的SQL_ID',plan_hash_value=>原目标SQL的PLAN HASH VALUE)

2)改写原目标SQL的SQL文本,在其中加入合适的Hint,直到加入Hint后的所改写的SQL能走出我们想要的执行计划,然后对改写后的SQL使用DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE手工生成新的执行计划所对应的SQL Plan Baseline。此时传入的参数如下所示:

dbms_spm.load_plans_from_cursor_cache(sql_id=>'加入合适Hint后改写SQL的SQL_ID',plan_hash_value=>加入合适Hint后改写SQL的PLAN HASH VALUE,sql_handle=>'原目标SQL在步骤(1)中所产生的SQL Plan Baseline的sql_handle')

3)使用DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE删除步骤(1)中手工生成的原目标SQL的初始执行计划所对应的SQL Plan Baseline。此时传入的参数如下所示:

dbms_spm.drop_sql_plan_baseline(sql_handle=>'原目标SQL在步骤(1)中所产生的SQL Plan Baseline的sql_handle',plan_name=>'原目标SQL在步骤(1)中所产生的SQL Plan Baseline的plan_name')

下面使用一个实例演示:

zx@MYDB>select /*+ no_index(t2 idx_t2) */ object_name,object_id from t2 where object_id=4;
 
OBJECT_NAME        OBJECT_ID
------------------------------ ----------
TAB$                    4
 
zx@MYDB>select * from table(dbms_xplan.display_cursor(null,null,'advanced'));
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  0n5z3wmf8qpgn, child number 0
-------------------------------------
select /*+ no_index(t2 idx_t2) */ object_name,object_id from t2 where
object_id=4
 
Plan hash value: 1513984157
 
--------------------------------------------------------------------------
| Id  | Operation    | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |  |  |  |   287 (100)|   |
|*  1 |  TABLE ACCESS FULL| T2   |     1 |    30 |   287   (1)| 00:00:04 |
--------------------------------------------------------------------------
 
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
 
   1 - SEL$1 / T2@SEL$1
 
Outline Data
-------------
 
  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.1')
      DB_VERSION('11.2.0.1')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      FULL(@"SEL$1" "T2"@"SEL$1")
      END_OUTLINE_DATA
  */
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter("OBJECT_ID"=4)
 
Column Projection Information (identified by operation id):
-----------------------------------------------------------
 
   1 - "OBJECT_NAME"[VARCHAR2,128], "OBJECT_ID"[NUMBER,22]
 
 
43 rows selected.
 
zx@MYDB>select sql_handle,plan_name,origin,enabled,accepted,sql_text from dba_sql_plan_baselines where sql_text like 'select /*+ no_index(t2 idx_t2)%';
 
no rows selected
 
zx@MYDB>var temp number
zx@MYDB>exec :temp :=dbms_spm.load_plans_from_cursor_cache(sql_id=>'0n5z3wmf8qpgn',plan_hash_value=>1513984157);
 
PL/SQL procedure successfully completed.
 
zx@MYDB>select sql_handle,plan_name,origin,enabled,accepted,sql_text from dba_sql_plan_baselines where sql_text like 'select /*+ no_index(t2 idx_t2)%';
 
SQL_HANDLE             PLAN_NAME          ORIGIN         ENABLED   ACCEPTED  SQL_TEXT
------------------------------ ------------------------------ -------------------- --------- --------- ----------------------------------------------------------------------
SYS_SQL_75b06ae056223f5f       SQL_PLAN_7bc3aw1b24guzb860bcf2 MANUAL-LOAD     YES       YES       select /*+ no_index(t2 idx_t2) */ object_name,object_id from t2 where object_i
                                                       d=4

从上述显示目标SQL初始执行计划为全表扫描,sql_id和plan hash value可以从执行计划中找到,由于没有启用自动捕获SQL Plan Baseline,一开始没有查到目标SQL对应的SQL Plan Baseline,手工生成后,可以查到全表扫描对应的SQL Plan Baseline。

改写原目标SQL,加入Hint后重新执行:

zx@MYDB>select /*+ index(t2 idx_t2) */ object_name,object_id from t2 where object_id=4;
 
OBJECT_NAME        OBJECT_ID
------------------------------ ----------
TAB$                    4
 
zx@MYDB>select * from table(dbms_xplan.display_cursor(null,null,'advanced'));
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  60txg87j30pvw, child number 0
-------------------------------------
select /*+ index(t2 idx_t2) */ object_name,object_id from t2 where
object_id=4
 
Plan hash value: 2008370210
 
--------------------------------------------------------------------------------------
| Id  | Operation          | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |       |      |      |  335 (100)|       |
|   1 |  TABLE ACCESS BY INDEX ROWID| T2     |     1 |    30 |   335   (0)| 00:00:05 |
|*  2 |   INDEX RANGE SCAN      | IDX_T2 |       1 |       |    1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------
 
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
 
   1 - SEL$1 / T2@SEL$1
   2 - SEL$1 / T2@SEL$1
 
Outline Data
-------------
 
  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.1')
      DB_VERSION('11.2.0.1')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      INDEX_RS_ASC(@"SEL$1" "T2"@"SEL$1" ("T2"."OBJECT_ID"))
      END_OUTLINE_DATA
  */
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("OBJECT_ID"=4)
 
Column Projection Information (identified by operation id):
-----------------------------------------------------------
 
   1 - "OBJECT_NAME"[VARCHAR2,128], "OBJECT_ID"[NUMBER,22]
   2 - "T2".ROWID[ROWID,10], "OBJECT_ID"[NUMBER,22]
 
 
46 rows selected.
 
zx@MYDB>exec :temp :=dbms_spm.load_plans_from_cursor_cache(sql_id=>'60txg87j30pvw',plan_hash_value=>2008370210,sql_handle=>'SYS_SQL_75b06ae056223f5f');
 
PL/SQL procedure successfully completed.
 
zx@MYDB>select sql_handle,plan_name,origin,enabled,accepted,sql_text from dba_sql_plan_baselines where sql_text like 'select /*+ no_index(t2 idx_t2)%';
 
SQL_HANDLE             PLAN_NAME          ORIGIN         ENABLED   ACCEPTED  SQL_TEXT
------------------------------ ------------------------------ -------------------- --------- --------- ----------------------------------------------------------------------
SYS_SQL_75b06ae056223f5f       SQL_PLAN_7bc3aw1b24guz24c6dbb6 MANUAL-LOAD     YES       YES       select /*+ no_index(t2 idx_t2) */ object_name,object_id from t2 where object_i
                                                       d=4
 
SYS_SQL_75b06ae056223f5f       SQL_PLAN_7bc3aw1b24guzb860bcf2 MANUAL-LOAD     YES       YES       select /*+ no_index(t2 idx_t2) */ object_name,object_id from t2 where object_i
                                                       d=4

从上述输出可以看出把改写过的SQL的新的执行计划所对应的SQL Plan Baseline已经成功生成,而且所有手工生成的SQL Plan Baseline的ENABLED和ACCEPTED的值均为YES,这是和自动捕获的SQL Plan Baseline不一样的地方。

Drop掉原执行计划(全表扫描)所对应的SQL Plan Baseline:

zx@MYDB>exec :temp := dbms_spm.drop_sql_plan_baseline(sql_handle=>'SYS_SQL_75b06ae056223f5f',plan_name=>'SQL_PLAN_7bc3aw1b24guzb860bcf2');
 
PL/SQL procedure successfully completed.
 
zx@MYDB>select sql_handle,plan_name,origin,enabled,accepted,sql_text from dba_sql_plan_baselines where sql_text like 'select /*+ no_index(t2 idx_t2)%';
 
SQL_HANDLE             PLAN_NAME          ORIGIN         ENABLED   ACCEPTED  SQL_TEXT
------------------------------ ------------------------------ -------------------- --------- --------- ----------------------------------------------------------------------
SYS_SQL_75b06ae056223f5f       SQL_PLAN_7bc3aw1b24guz24c6dbb6 MANUAL-LOAD     YES       YES       select /*+ no_index(t2 idx_t2) */ object_name,object_id from t2 where object_i
                                                       d=4

再次执行原目标SQL,并查看执行计划

zx@MYDB>select /*+ no_index(t2 idx_t2) */ object_name,object_id from t2 where object_id=4;
 
OBJECT_NAME        OBJECT_ID
------------------------------ ----------
TAB$                    4
 
zx@MYDB>select * from table(dbms_xplan.display_cursor(null,null,'advanced'));
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  0n5z3wmf8qpgn, child number 2
-------------------------------------
select /*+ no_index(t2 idx_t2) */ object_name,object_id from t2 where
object_id=4
 
Plan hash value: 2008370210
 
--------------------------------------------------------------------------------------
| Id  | Operation          | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |       |      |      |  335 (100)|       |
|   1 |  TABLE ACCESS BY INDEX ROWID| T2     |     1 |    30 |   335   (0)| 00:00:05 |
|*  2 |   INDEX RANGE SCAN      | IDX_T2 |       1 |       |    1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------
 
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
 
   1 - SEL$1 / T2@SEL$1
   2 - SEL$1 / T2@SEL$1
 
Outline Data
-------------
 
  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.1')
      DB_VERSION('11.2.0.1')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      INDEX_RS_ASC(@"SEL$1" "T2"@"SEL$1" ("T2"."OBJECT_ID"))
      END_OUTLINE_DATA
  */
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   2 - access("OBJECT_ID"=4)
 
Column Projection Information (identified by operation id):
-----------------------------------------------------------
 
   1 - "OBJECT_NAME"[VARCHAR2,128], "OBJECT_ID"[NUMBER,22]
   2 - "T2".ROWID[ROWID,10], "OBJECT_ID"[NUMBER,22]
 
Note
-----
   - SQL plan baseline SQL_PLAN_7bc3aw1b24guz24c6dbb6 used for this statement
 
 
50 rows selected.

从上述输出可以看出,原目标SQL已经走了新的执行计划(索引范围扫描),而且Note部分也有提示“SQL plan baseline SQL_PLAN_7bc3aw1b24guz24c6dbb6 used for this statement”说明走了SPM。

 


    
 
 

您可能感兴趣的文章:

  • 怎么写一个Shell来执行这样的功能,访问Oracle数据库,然后执行一个SQL脚本,生成一个文件。急!
  • win2000+jbuilder6+oracle817编出的程序,在win2000下执行很好,在win98下却访问不了oracle数据库
  • oracle 可以在crontab 中定时执行吗?
  • oracle sql执行过程(流程图)
  • linux能够通过执行脚本添加oracle数据库的用户吗
  • ORACLE安装时/tmp/orainstRoot.sh 执行发生错误
  • 求救:HPUNIX下的ORACLE7执行select * from tablename提示权限不足!!
  • 为什么 export ORACLE_SID=test写在程序里面就不会执行?
  • 请问在 Linux 下如何用代码实现连接oracle数据库 并 执行 SQL 语句?
  • shell调用oracle储存过程,怎么判断储存过程执行结果是否正确
  • shell 执行oracle sql脚本的问题
  • oracle单库彻底删除干净的执行步骤
  • 查看Oracle的执行计划一句话命令
  • 关于ORACLE中执行批处理的问题
  • oracle中得到一条SQL语句的执行时间的两种方式
  • oracle导出sql语句的结果集和保存执行的sql语句(深入分析)
  • Nagios check_oracle_health 关于执行SQL问题
  • 执行Commit时Oracle做哪些工作
  • RedHat AS 4 安装oracle9i的时候,执行Disk1下的runInstaller后提示正在初始化虚拟机,请等待后就再无反应
  • JBUILDER如何执行ORACLE的储存过程
  • 为Oracle增加计划任务
  • 利用windows任务计划实现oracle的定期备份
  • Oracle数据库设置任务计划备份一周的备份记录
  • Oracle公布SPARC五年计划和Solaris 11上市时间
  • Oracle密谋B计划 JDK 7或成跳票王
  • Oracle中获取执行计划的几种方法分析
  • 解析Oracle 8i/9i的计划稳定性
  • Oracle中使用DBMS_XPLAN处理执行计划详解
  • ORACLE数据库查看执行计划的方法
  • Oracle中基于hint的3种执行计划控制方法详细介绍
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 如何设置让Oracle SQL Developer显示的时间包含时分秒
  • Oracle 数据库开发工具 Oracle SQL Developer
  • 取数据库前几条数据(sql server、oracle、mysql)的sql写法
  • Oracle发布Oracle SQL Developer 1.2数据库开发工具 帮助用户简化开发工作
  • oracle用什么SQL语句判断表存不存在
  • 与jsp搭配,oracle好?sql server好?
  • Oracle开发工具 Oracle SQL Handler
  • Oracle与SQL Server区别在哪里
  • Oracle的SQL语句中如何处理‘&’符号
  • Oracle捕获问题SQL解决CPU过渡消耗
  • Oracle中SQL语句连接字符串的符号使用介绍
  • Unix系统下oracle sql排版
  • oracle.xml.sql.query.OracleXMLQuery
  • oracle SQL解析步骤小结
  • 怎么在java中向一个sql语句传参数,就像oracle的proc一样啊?
  • Oracle中DBMS_SQL解析SQL语句的流程
  • Linux/UNIX下,C++程序通过那些步骤访问Oracle或者Sybase SQL数据库?
  • Oracle SQL使用时注意自己的输入
  • 用oracle pl/sql 从A unix机器,去读取B unix机器上的一个文件,怎么实现?
  • 请问哪里可以找到 package oracle.sql.*
  • Oracle Sql语句长度限制问题及解决
  • Oracle 12c发布简单介绍及官方下载地址
  • JBUILDER如何执行ORACLE的储存过程 iis7站长之家
  • oracle 11g最新版官方下载地址
  • 请问su oracle 和su - oracle有什么不同?
  • Oracle 数据库(oracle Database)Select 多表关联查询方式
  • 虚拟机装Oracle R12与Oracle10g
  • Oracle数据库(Oracle Database)体系结构及基本组成介绍
  • Oracle EBS R12 支持 Oracle Database 11g
  • Oracle 10g和Oracle 11g网格技术介绍
  • SCO unix下安装oracle,但没有光盘,请大家推荐一个oracle下载站点(unix版本的)。谢谢!!!!


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3