oracle 11G 执行计划管理
2016-10-11 17:38
441 查看
一、oracle 11G 执行计划管理原理
oracle11G开始,引入了sql执行计划管理(SQL Plan Management)这个新特性
通过启用该特性,某条语句如果产生了一个新的执行计划,只有在它的性能比原来的执行计划好的情况下,才会被使用。
优化器维护两个列表:
plan history
plan baseline
11G也支持手工维护plan history,作为对自动维护plan history的功能补充
plan baseline是plan history的一个子集
1.初始化参数 OPTIMIZER_CAPTURE_PLAN_BASELINES 设置为true,则会自动捕获SQL的执行计划。
SQL第一次执行,plan history和plan baseline列表都为空,这时产生的执行计划会同时进入到plan history,plan baseline列表中
以后同一语句所产生的新执行计划都会先进入到plan history中,然后同plan baseline中的执行计划进行比较,只有成本比plan baseline
中的要低才会进入到plan baseline中
2.使用dbms_spm包手工处理,这可以让你手工管理SQL Plan baseline。使用该包,你可以直接将SQL的执行计划从 shared pool里加载到
plan baseline里,也可以将已经存在的SQL Tuning Set加载到plan baseline里。同时,dbms_spm还可以将plan history里的执行计划加入到
plan baseline里。反之也可以用该包将plan baseline里的执行计划移出去。
3.plan baseline 里的执行计划是如何被使用的呢?
oracle 提供了一个初始化参数:OPTIMIZER_USE_PLAN_BASELINES,该参数缺省为true,表示要求优化器考虑使用plan baseline里的执行计划,
每次优化器解析SQL语句的时候,首先仍然使用11G之前的传统方式产生一个成本最低的执行计划,然后看初始化参数:
OPTIMIZER_USE_PLAN_BASELINES是否设置为true,如果为false,则直接返回所生成的执行计划。否则如果为true,则去plan_history里找是否存在
相同的执行计划,如果找到,则再去plan baseline里找是否存在相同的执行计划,如果也找到了,则直接返回该执行计划。如果在plan_history里没找到
相同的执行计划,则将生成的执行计划加入到plan history里,然后将执行计划与plan baseline里已经存在的进行比较,看哪个成本低就选取哪个执行计划
SQL语句的plan history以及plan baseline所涉及到的表是存放在SQL Management Base (SMB)里的,SMB里同样也存放了SQL Profiles。而SMB是数据字典的一部分,存放在SYSAUX表空间里。SMB所占用的空间会自动定期的删除。
二、执行计划管理的测试
oracle11g提供了一个视图:dba_sql_plan_baselines,可以在该视图里查询某条 SQL语句相关的plan history以及plan baseline。我们来看下面的例子
首先创建一个测试表.
尽管执行两次,但是这时去查询dba_sql_plan_baselines,试图找到SQL文本为select * from t1 where skew=200的记录时,会发现没有记录,因为
optimizer_capture_sql_plan_baselines缺省为false。我们将该参数设置为true以后继续测试。
我们可以看到,文本为"select * from t1 where skew=200"的SQL语句在plan history里产生了一个执行计划。其中,
sql_handle表示SQL语句的句柄;
plan_name则表示SQL执行计划的名字;
origin表示该执行计划是如何进入到plan_history的,该列值为AUTO-CAPTURE,则说明是由优化器自动加入的,
如果是MANUAL则说明是由DBA手工加入的;
enabled表示是否被启用了;如果某个执行计划为禁用,则优化器根本就不会考虑使用该计划;
accepted表示是否接受,也就是是否进入了plan baseline。
autopurge表示是否为定期自动删除。
我们继续测试,在skew列上添加一个索引,从而让原来的SQL不走全表扫描,而改走索引扫描。
这时我们可以看到,dba_sql_plan_baselines视图里多了一个执行计划,也就是我们后面那个使用了索引扫描的执行计划。而该执行计划的accepted为NO,说明该计划并没有
进入到plan baseline里,但进入了plan history里。
这时我们可以通过调用dbms_spm包来手工将走索引的执行计划加入到plan baseline里。如下所示,将accepted改为YES。
执行DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE前:
执行DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE后:
不过后来发现,要把accepted变为NO却是不可以了,只有先删除,然后再重新生成让优化器自动加入到plan history中
oracle11G开始,引入了sql执行计划管理(SQL Plan Management)这个新特性
通过启用该特性,某条语句如果产生了一个新的执行计划,只有在它的性能比原来的执行计划好的情况下,才会被使用。
优化器维护两个列表:
plan history
plan baseline
11G也支持手工维护plan history,作为对自动维护plan history的功能补充
plan baseline是plan history的一个子集
1.初始化参数 OPTIMIZER_CAPTURE_PLAN_BASELINES 设置为true,则会自动捕获SQL的执行计划。
SQL第一次执行,plan history和plan baseline列表都为空,这时产生的执行计划会同时进入到plan history,plan baseline列表中
以后同一语句所产生的新执行计划都会先进入到plan history中,然后同plan baseline中的执行计划进行比较,只有成本比plan baseline
中的要低才会进入到plan baseline中
2.使用dbms_spm包手工处理,这可以让你手工管理SQL Plan baseline。使用该包,你可以直接将SQL的执行计划从 shared pool里加载到
plan baseline里,也可以将已经存在的SQL Tuning Set加载到plan baseline里。同时,dbms_spm还可以将plan history里的执行计划加入到
plan baseline里。反之也可以用该包将plan baseline里的执行计划移出去。
3.plan baseline 里的执行计划是如何被使用的呢?
oracle 提供了一个初始化参数:OPTIMIZER_USE_PLAN_BASELINES,该参数缺省为true,表示要求优化器考虑使用plan baseline里的执行计划,
每次优化器解析SQL语句的时候,首先仍然使用11G之前的传统方式产生一个成本最低的执行计划,然后看初始化参数:
OPTIMIZER_USE_PLAN_BASELINES是否设置为true,如果为false,则直接返回所生成的执行计划。否则如果为true,则去plan_history里找是否存在
相同的执行计划,如果找到,则再去plan baseline里找是否存在相同的执行计划,如果也找到了,则直接返回该执行计划。如果在plan_history里没找到
相同的执行计划,则将生成的执行计划加入到plan history里,然后将执行计划与plan baseline里已经存在的进行比较,看哪个成本低就选取哪个执行计划
SQL语句的plan history以及plan baseline所涉及到的表是存放在SQL Management Base (SMB)里的,SMB里同样也存放了SQL Profiles。而SMB是数据字典的一部分,存放在SYSAUX表空间里。SMB所占用的空间会自动定期的删除。
二、执行计划管理的测试
oracle11g提供了一个视图:dba_sql_plan_baselines,可以在该视图里查询某条 SQL语句相关的plan history以及plan baseline。我们来看下面的例子
首先创建一个测试表.
SQL> create table t1(skew number,padding varchar2(100)); Table created. SQL> SQL> insert into t1 select rownum,object_name from dba_objects; 86632 rows created. SQL> commit;
SQL> set autot trace exp stat SQL> select * from t1 where skew=200; Execution Plan ---------------------------------------------------------- Plan hash value: 3617692013 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 5 | 325 | 116 (1)| 00:00:02 | |* 1 | TABLE ACCESS FULL| T1 | 5 | 325 | 116 (1)| 00:00:02 | -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("SKEW"=200) Note ----- - dynamic sampling used for this statement (level=2) Statistics ---------------------------------------------------------- 10 recursive calls 0 db block gets 497 consistent gets 0 physical reads 0 redo size 607 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 2 sorts (memory) 0 sorts (disk) 1 rows processed SQL> / Execution Plan ---------------------------------------------------------- Plan hash value: 3617692013 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 5 | 325 | 116 (1)| 00:00:02 | |* 1 | TABLE ACCESS FULL| T1 | 5 | 325 | 116 (1)| 00:00:02 | -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("SKEW"=200) Note ----- - dynamic sampling used for this statement (level=2) Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 423 consistent gets 0 physical reads 0 redo size 607 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
SQL> select * from dba_sql_plan_baselines; no rows selected
尽管执行两次,但是这时去查询dba_sql_plan_baselines,试图找到SQL文本为select * from t1 where skew=200的记录时,会发现没有记录,因为
optimizer_capture_sql_plan_baselines缺省为false。我们将该参数设置为true以后继续测试。
SQL> alter session set optimizer_capture_sql_plan_baselines=true; Session altered. SQL> select * from t1 where skew=200; SKEW ---------- PADDING -------------------------------------------------------------------------------- 200 I_SQL$TEXT_PKEY SQL> / SKEW ---------- PADDING -------------------------------------------------------------------------------- 200 I_SQL$TEXT_PKEY SQL> select signature,sql_handle,plan_name,origin,enabled,accepted,autopurge from dba_sql_plan_baselines where sql_text like 'select * from t1 where skew=200'; SIGNATURE ---------- SQL_HANDLE -------------------------------------------------------------------------------- PLAN_NAME -------------------------------------------------------------------------------- ORIGIN ENABLED ACCEPTED AUTOPURGE ------------------------------------------ --------- --------- --------- 1.2376E+19 SQL_abc0a2c042fa089c SQL_PLAN_arh52s11gn24wdbd90e8e AUTO-CAPTURE YES YES YES
我们可以看到,文本为"select * from t1 where skew=200"的SQL语句在plan history里产生了一个执行计划。其中,
sql_handle表示SQL语句的句柄;
plan_name则表示SQL执行计划的名字;
origin表示该执行计划是如何进入到plan_history的,该列值为AUTO-CAPTURE,则说明是由优化器自动加入的,
如果是MANUAL则说明是由DBA手工加入的;
enabled表示是否被启用了;如果某个执行计划为禁用,则优化器根本就不会考虑使用该计划;
accepted表示是否接受,也就是是否进入了plan baseline。
autopurge表示是否为定期自动删除。
我们继续测试,在skew列上添加一个索引,从而让原来的SQL不走全表扫描,而改走索引扫描。
SQL> create index idx_skew on t1(skew); Index created. SQL> exec dbms_stats.gather_table_stats('SYS','T1',cascade=>true); PL/SQL procedure successfully completed. SQL> select * from t1 where skew=200; SQL> select signature,sql_handle,plan_name,origin,enabled,accepted,fixed,autopurge from dba_sql_plan_baselines where sql_text like 'select * from t1 where skew=200'; SIGNATURE SQL_HANDLE PLAN_NAME ORIGIN ENABLED ACCEPTED FIXED AUTOPURGE ---------- ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ ------------------------------------------ --------- --------- --------- --------- 1.2376E+19 SQL_abc0a2c042fa089c SQL_PLAN_arh52s11gn24w22142e90 AUTO-CAPTURE YES NO NO YES 1.2376E+19 SQL_abc0a2c042fa089c SQL_PLAN_arh52s11gn24wdbd90e8e AUTO-CAPTURE YES YES NO YES
这时我们可以看到,dba_sql_plan_baselines视图里多了一个执行计划,也就是我们后面那个使用了索引扫描的执行计划。而该执行计划的accepted为NO,说明该计划并没有
进入到plan baseline里,但进入了plan history里。
这时我们可以通过调用dbms_spm包来手工将走索引的执行计划加入到plan baseline里。如下所示,将accepted改为YES。
执行DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE前:
SQL> select signature,sql_handle,plan_name,origin,enabled,accepted,fixed,autopurge from dba_sql_plan_baselines where plan_name='SQL_PLAN_arh52s11gn24w22142e90'; SIGNATURE SQL_HANDLE PLAN_NAME ORIGIN ENABLED <span style="color:#ff0000;">ACCEPTED </span>FIXED AUTOPURGE ---------- ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ ------------------------------------------ --------- --------- --------- --------- 1.2376E+19 SQL_abc0a2c042fa089c SQL_PLAN_arh52s11gn24w22142e90 AUTO-CAPTURE YES <span style="color:#ff0000;">NO </span>NO YES
执行DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE后:
SQL> declare l_plans_altered clob; begin l_plans_altered := DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE(sql_handle => 'SQL_abc0a2c042fa089c', plan_name => 'SQL_PLAN_arh52s11gn24w22142e90', time_limit => DBMS_SPM.AUTO_LIMIT, verify => 'yes', commit => 'yes'); end; 2 3 4 5 6 7 8 9 10 / PL/SQL procedure successfully completed. SQL> SQL> select signature,sql_handle,plan_name,origin,enabled,accepted,fixed,autopurge from dba_sql_plan_baselines where plan_name='SQL_PLAN_arh52s11gn24w22142e90'; SIGNATURE SQL_HANDLE PLAN_NAME ORIGIN ENABLED <span style="color:#ff0000;">ACCEPTED </span>FIXED AUTOPURGE ---------- ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ ------------------------------------------ --------- --------- --------- --------- 1.2376E+19 SQL_abc0a2c042fa089c SQL_PLAN_arh52s11gn24w22142e90 AUTO-CAPTURE YES <span style="color:#ff0000;">YES</span> NO YES SQL>
不过后来发现,要把accepted变为NO却是不可以了,只有先删除,然后再重新生成让优化器自动加入到plan history中
SQL> DECLARE l_plans_dropped PLS_INTEGER; BEGIN l_plans_dropped := DBMS_SPM.drop_sql_plan_baseline(sql_handle => 'SQL_abc0a2c042fa089c', plan_name => 'SQL_PLAN_arh52s11gn24w22142e90'); end; 2 3 4 5 6 7 / PL/SQL procedure successfully completed.
相关文章推荐
- Oracle 11g 执行计划管理概述
- 点评Oracle 11g新特性之执行计划管理
- Oracle 11g 执行计划管理1
- Oracle 11g 执行计划管理2
- Oracle 11g 中SQL 执行计划不稳定
- oracle 11g BaseLine(基线)指定application中不可修改sql的执行计划
- Oracle 11g r2全外连接优化执行计划(一)
- 『ORACLE』授予hr用户查看执行计划权限(11g)
- Oracle 11g r2全外连接优化执行计划(三)
- Oracle 11g如何清除share pool中某条SQL的执行计划
- 执行计划的管理---baseline(11g)
- Oracle 数据库 11g新特性:自适应游标与 SQL 计划管理
- 11g新特性SQL执行计划管理(SQL Plan Management) (1)
- Oracle性能优化之执行计划管理_超越OCP精通Oracle视频教程培训31
- Oracle Job 任务计划管理[作业,定期执行任务]
- Oracle Job 任务计划管理[作业,定期执行任务]
- Oracle 11g r2全外连接优化执行计划(二)
- Oracle 11g 递归+ exists执行计划的改变
- oracle SPM 执行计划管理
- oracle怎么实现每天定时执行一个计划任务