参考文档: Oracle database 11gr2 性能调整与优化
1 启用捕获并多次运行sql语句,以便于SPM判断语句是否可重复,然后关闭捕获
alter session set optimizer_capture_sql_plan_baselines=true;
select * /* ebk1 */ from scott.emp where job='PRESIDENT';
select * /* ebk1 */ from scott.emp where job='PRESIDENT';
alter session set optimizer_capture_sql_plan_baselines=false;
2 查询dba_sql_plan_baselines,确定SQL语句在SPM中的状态
select plan_name,sql_handle,enabled,accepted,fixed,module,sql_text from dba_sql_plan_baselines;
3 增加索引以改变环境,并再次运行该SQL语句
create index idx_job on scott.emp(job);
alter session set optimizer_capture_sql_plan_baselines=true;
select * /* ebk1 */ from scott.emp where job='PRESIDENT';
select * /* ebk1 */ from scott.emp where job='PRESIDENT';
alter session set optimizer_capture_sql_plan_baselines=false;
4 查询dba_sql_plan_baselines,确定SQL语句在SPM中的状态
select plan_name,sql_handle,enabled,accepted,fixed,module,sql_text from dba_sql_plan_baselines;
设置optimizer_use_sql_plan_baseline为false,并允许优化器选择计划
然后设置额optimizer_use_sql_plan_baseline为true,强制优化器在计划基线中仅选择一个已接受的计划
在第一种情况下,优化器选择了使用索引的计划。但是在第二种情况下,没有使用。因为这是未被接受的计划。
alter system set optimizer_use_sql_plan_baselines=true;
explain plan for
select * /* ebk1 */ from scott.emp where job='PRESIDENT';
select * from table(dbms_xplan.display(null,null,'basic'))
SYS@test>select * from table(dbms_xplan.display(null,null,'basic'));
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3956160932
----------------------------------
| Id | Operation | Name |
----------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS FULL| EMP |
----------------------------------
8 rows selected.
alter system set optimizer_use_sql_plan_baselines=false;
explain plan for
select * /* ebk1 */ from scott.emp where job='PRESIDENT';
select * from table(dbms_xplan.display(null,null,'basic'))
SYS@test>select * from table(dbms_xplan.display(null,null,'basic'));
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3894156048
-----------------------------------------------
| Id | Operation | Name |
-----------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID| EMP |
| 2 | INDEX RANGE SCAN | IDX_JOB |
-----------------------------------------------
9 rows selected.
接下来,改善SQL计划,允许accepted状态为NO的计划变成yes 。
set serveroutput on
set long 10000
declare
report clob;
begin
report:=dbms_spm.evolve_sql_plan_baseline(
sql_handle=>'SQL_5351f0dc28458c6a');
dbms_output.put_line(report);
end;
/
SYS@test>set serveroutput on
set long 10000
declare
report clob;
begin
report:=dbms_spm.evolve_sql_plan_baseline(
sql_handle=>'SQL_5351f0dc28458c6a');
dbms_output.put_line(report);
end;
/SYS@test>SYS@test> 2 3 4 5 6 7 8
-------------------------------------------------------------------------------
Evolve SQL Plan Baseline
Report
-------------------------------------------------------------------------
------
Inputs:
-------
SQL_HANDLE = SQL_5351f0dc28458c6a
PLAN_NAME =
TIME_LIMIT = DBMS_SPM.AUTO_LIMIT
VERIFY = YES
COMMIT = YES
Plan:
SQL_PLAN_56nghvhn4b33aa2f1f054
------------------------------------
Plan was
verified: Time used 0 seconds.
Plan passed performance criterion: 3 times
better than baseline plan.
Plan was changed to an accepted plan.
Baseline Plan Test Plan Stats Ratio
------------- --------- -----------
Execution Status:
COMPLETE COMPLETE
Rows Processed: 1
1
Elapsed Time(ms): .011 .008 1.38
CPU Time(ms): 0 0
Buffer Gets:
6 2 3
Physical Read Requests: 0
0
Physical Write Requests: 0 0
Physical Read
Bytes: 0 0
Physical Write Bytes:
0 0
Executions: 1
1
-----------------------------------------------------------------------------
--
Report
Summary
------------------------------------------------------------------------
-------
Number of plans verified: 1
Number of plans accepted: 1
PL/SQL procedure successfully completed.
使用语句,或者EM查看,这个语句已经变成接受的了
这个时候,如果optimizer_use_sql_plan_baseline 为true,运行sql就会使用新的已接受的计划,因为
他的性能比其他已接受的计划好
alter system set optimizer_use_sql_plan_baselines=true;
explain plan for
select * /* ebk1 */ from scott.emp where job='PRESIDENT';
select * from table(dbms_xplan.display(null,null,'basic'))
SYS@test>explain plan for
select * /* ebk1 */ from scott.emp where job='PRESIDENT'; 2
Explained.
SYS@test>select * from table(dbms_xplan.display(null,null,'basic'));
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3894156048
-----------------------------------------------
| Id | Operation | Name |
-----------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID| EMP |
| 2 | INDEX RANGE SCAN | IDX_JOB |
-----------------------------------------------
9 rows selected.
SYS@test>
使用固定的SQL执行计划
declare
l_plans_altered PLS_INTEGER;
begin
l_plans_altered :=dbms_spm.alter_sql_plan_baseline(
sql_handle=>'SQL_5351f0dc28458c6a',
plan_name=> null,
attribute_name=> 'fixed',
attribute_value=>'YES');
end;
再次查询,已经固定。或者在EM上查询
select plan_name,sql_handle,enabled,accepted,fixed,module,sql_text from dba_sql_plan_baselines;
删除计划:
set serveroutput on
declare
l_plan_dropped pls_integer;
begin
l_plan_dropped:=dbms_spm.drop_sql_plan_baseline(
sql_handle=>'SQL_5351f0dc28458c6a',
plan_name=>null);
end;
执行完毕后,在EM上看,看不到了
END。
补充,其实,这个知识点,是11gr2 OCM考试里面的一道题目。考试的时候,没有这个这么复杂,直接在EM上操作,很方便。也很迅速就完毕了。但是知道原理,还是好一些。