使用SQL Plan Baselines影响已加入hints的SQL执行计划
reference DBA手记2
1.SQL Plan Baseline(执行计划基线)概论
如果应用程序中强行加了hints(提示),可以使用SQL Profile来稳定执行计划,除了使用SQL Profile方式,还可以使用SQL Plan Baseline(执行计划基线),该特性从11g开始支持,同时取代了10g之前的stored outline功能,因为stored outline(存储提纲)不够智能,而且其操作也比较繁琐。
主要作用:
稳定给定SQL语句的执行计划,防止执行环境或对象统计信息等等因子的改变对SQL语句的执行计划产生影响!
减少数据库中出现SQL语句性能退化的概率,理论上不允许一条语句切换到一个比已经执行过的执行计划慢很多的新的执行计划上!
SQL执行计划基线保存在数据字典中,查询优化器会自动判断使用他们。
SQL Plan Baseline可以通过脚本或图形界面方式来配置管理,这里使用脚本完成,即调用dbms_spm。
2.创建测试表,并收集统计信息
select sql_handle,plan_name,dbms_lob.substr(sql_text,60,1) sql_text,ACCEPTED from dba_sql_plan_baselines;
alter system flush shared_pool;
sys@ORCL>create table big_table as select rownum as id,t.* from all_objects t;
Table created.
sys@ORCL>create index idx_big_table_id on big_table(id);
Index created.
sys@ORCL>exec dbms_stats.gather_table_stats(user,'big_table');
PL/SQL procedure successfully completed.
3.执行查询测试
sys@ORCL>set autotrace on explain
sys@ORCL>select count(*) from big_table where id between 100 and 200;
COUNT(*)
----------
101
Execution Plan
----------------------------------------------------------
Plan hash value: 2068851779
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 5 | 2 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
|* 2 | INDEX RANGE SCAN| IDX_BIG_TABLE_ID | 102 | 510 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID">=100 AND "ID"<=200)
4.强行加入full hints使其变为全表扫描
sys@ORCL>select /*+full(t)*/ count(*) from big_table t where id between 100 and 200;
COUNT(*)
----------
101
Execution Plan
----------------------------------------------------------
Plan hash value: 599409829
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 5 | 345 (1)| 00:00:05 |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
|* 2 | TABLE ACCESS FULL| BIG_TABLE | 102 | 510 | 345 (1)| 00:00:05 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("ID"<=200 AND "ID">=100)
5.启用SQL Plan Baselines自动获取
----利用SQL Plan Baselines获取更优的执行计划
sys@ORCL>set autot off
sys@ORCL>show parameter optimizer_use_sql_plan_baselines
NAME TYPE VALUE
------------------------------------ ---------------------- ------------------------------
optimizer_use_sql_plan_baselines boolean TRUE
sys@ORCL>select /*+full(t)*/ count(*) from big_table t where id between 100 and 200;
COUNT(*)
----------
101
sys@ORCL>select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
SQL_ID 9babjv8yq8ru3, child number 0
BEGIN DBMS_OUTPUT.GET_LINES(:LINES, :NUMLINES); END;
NOTE: cannot fetch plan for SQL_ID: 9babjv8yq8ru3, CHILD_NUMBER: 0
Please verify value of SQL_ID and CHILD_NUMBER;
It could also be that the plan is no longer in cursor cache (check v$sql_plan)
8 rows selected.
sys@ORCL>set serveroutput off
sys@ORCL>select /*+full(t)*/ count(*) from big_table t where id between 100 and 200;
sys@ORCL>select /*+full(t)*/ count(*) from big_table t where id between 100 and 200;
sys@ORCL>select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
SQL_ID 84nabsvnwf9kb, child number 0
-------------------------------------
select /*+full(t)*/ count(*) from big_table t where id between 100 and
200
Plan hash value: 599409829
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 345 (100)| |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
|* 2 | TABLE ACCESS FULL| BIG_TABLE | 102 | 510 | 345 (1)| 00:00:05 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(("ID"<=200 AND "ID">=100))
20 rows selected.
DECLARE
l_plans_loaded PLS_INTEGER;
BEGIN
l_plans_loaded := DBMS_SPM.load_plans_from_cursor_cache(sql_id => '84nabsvnwf9kb',plan_hash_value=>null);
END;
/
6.修改基线
----查看对应的sql_handle,以便用新的执行计划替换
select sql_handle,plan_name,dbms_lob.substr(sql_text,60,1) sql_text,ACCEPTED from dba_sql_plan_baselines;
SQL_HANDLE PLAN_NAME SQL_TEXT ACCEPT
----------------- -------------------------- ------------------------ ---------------------------------
SQL_17dc586bdecfee90 SQL_PLAN_1gr2sdggczvnhc74815fa select /*+full(t)*/ count(*) from big_table t where id betwe YES
----执行不加hint的sql,使用dbms_spm从library cache中加载该执行计划
sys@ORCL>select count(*) from big_table t where id between 100 and 200;
COUNT(*)
----------
101
sys@ORCL>select prev_sql_id from v$session where sid=userenv('sid');
PREV_SQL_ID
--------------------------
1zy136qv3g3k9
sys@ORCL>select * from table(dbms_xplan.display_cursor(sql_id => '1zy136qv3g3k9'));
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
SQL_ID 1zy136qv3g3k9, child number 0
-------------------------------------
select count(*) from big_table t where id between 100 and 200
Plan hash value: 2068851779
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
|* 2 | INDEX RANGE SCAN| IDX_BIG_TABLE_ID | 102 | 510 | 2 (0)| 00:00:01
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID">=100 AND "ID"<=200)
19 rows selected.
----修改基线
var rtn number
exec :rtn :=dbms_spm.load_plans_from_cursor_cache(sql_id =>'1zy136qv3g3k9',sql_handle => 'SQL_17dc586bdecfee90');
sys@ORCL>select sql_handle,plan_name,dbms_lob.substr(sql_text,60,1) sql_text,ACCEPTED from dba_sql_plan_baselines;
SQL_HANDLE PLAN_NAME SQL_TEXT ACCEPT
------------ -------------- -------------------------- -----------------------
SQL_17dc586bdecfee90 SQL_PLAN_1gr2sdggczvnhc41cefbc
select /*+full(t)*/ count(*) from big_table t where id betwe
YES
SQL_17dc586bdecfee90 SQL_PLAN_1gr2sdggczvnhc74815fa
select /*+full(t)*/ count(*) from big_table t where id betwe
YES
sys@ORCL>select /*+full(t)*/ count(*) from big_table t where id between 100 and 200;
sys@ORCL>select /*+full(t)*/ count(*) from big_table t where id between 100 and 200;
sys@ORCL>select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
SQL_ID 84nabsvnwf9kb, child number 0
-------------------------------------
select /*+full(t)*/ count(*) from big_table t where id between 100 and
200
Plan hash value: 599409829
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 345 (100)| |
| 1 | SORT AGGREGATE | | 1 | 5 | | |
|* 2 | TABLE ACCESS FULL| BIG_TABLE | 102 | 510 | 345 (1)| 00:00:05 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(("ID"<=200 AND "ID">=100))
Note
-----
- SQL plan baseline SQL_PLAN_1gr2sdggczvnhc74815fa used for this statement
24 rows selected.
7.删除原有基线
select sql_handle,plan_name,dbms_lob.substr(sql_text,60,1) sql_text,ACCEPTED from dba_sql_plan_baselines;
sys@ORCL>var rtn number
sys@ORCL>exec :rtn :=dbms_spm.drop_sql_plan_baseline(plan_name => 'SQL_PLAN_1gr2sdggczvnhc74815fa');
sys@ORCL>select /*+full(t)*/ count(*) from big_table t where id between 100 and 200;
sys@ORCL>select /*+full(t)*/ count(*) from big_table t where id between 100 and 200;
sys@ORCL>select * from table(dbms_xplan.display_cursor);
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
SQL_ID 84nabsvnwf9kb, child number 1
-------------------------------------
select /*+full(t)*/ count(*) from big_table t where id between 100 and
200
Plan hash value: 2068851779
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)|
| 1 | SORT AGGREGATE | | 1 | 5 | |
|* 2 | INDEX RANGE SCAN| IDX_BIG_TABLE_ID | 102 | 510 | 2 (0)| 00:00:01
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID">=100 AND "ID"<=200)
Note
-----
- SQL plan baseline SQL_PLAN_1gr2sdggczvnhc41cefbc used for this statement
24 rows selected.
所以,当我们在无法改变应用程序的sql语句时,可以利用sql plan baselines 来影响其执行计划。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30130773/viewspace-2121696/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/30130773/viewspace-2121696/
- 使用V$SQL_PLAN视图获取曾经执行过的SQL语句执行计划
- 应用程序对Sqlserver进行SQL查询使用与不使用参数对执行计划的影响
- sql plan baselines(计划基线)Oracle 原文
- 从一个SQL使用了不理想的执行计划说开,浅谈执行计划如何估算cache信息的影响及系统统计信息的收集等(2010-10-15)
- Scripts:根据sql_id从AWR中查询执行计划(个人比较喜欢使用这个)display_awr_plan.sql
- Oracle 性能调优之:使用 V$SQL_PLAN 视图查询内存中的执行计划
- 使用mysql profiles 来查看sql 语句执行计划
- oracle--如何干预执行计划(使用hints提示)
- Oracle 执行计划及Hints的介绍使用
- sql server execution plan - 执行计划的诡异 ( 二 )
- MySQL中使用explain和profile分析SQL执行计划和性能
- 【转】 SQL优化--使用 EXISTS 代替 IN 和 inner join来选择正确的执行计划
- oracle--如何干预执行计划(使用hints提示)
- 如何使用ordered提示改变SQL执行计划
- Scripts:打印执行计划中AWR的执行计划信息awr_plan_stats.sql
- 使用mysql profiles 来查看sql 语句执行计划
- Oracle执行计划使用分析SQL执行效率
- 使用coe_xfr_sql_profile 绑定执行计划简单练习
- 11G新特性SQL PLAN BASLINE 执行计划基线
- 使用 EXPLAIN PLAN 获取SQL语句执行计划