oracle SPM

oracle 9i,10g,11g執行計劃的固定一直是oracle的心病之一,雖然CBO很強了,在10g裏咱們用outline,引入sql_profile,11g裏用sql_profile,引入sql_plan_baseline
1 相關參數
optimizer_capture_sql_plan_baselines默認值false,即不採用自動捕獲
optimizer_use_sql_plan_baselines 默認值true,即優先使用dba_sql_plan_baselines裏的執行計劃;
2 默認參數測試
有條SQL很簡單:select * from hr.emp where EMPLOYEE_ID=206;
此表無索引,無主鍵,就是一個最普通的堆表
執行計劃無懸念:全表掃苗:sql

SQL> select* from table(dbms_xplan.display_cursor('76rrg3a06j24n',0)); 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
SQL_ID  76rrg3a06j24n, child number 0
-------------------------------------
select * from hr.emp where EMPLOYEE_ID=206
Plan hash value: 3956160932
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |       |       |     2 (100)|          |
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |   133 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------

創建基線:oracle

declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.load_plans_from_cursor_cache(sql_id=>'76rrg3a06j24n');
end;

檢查基線:ide

select sql_handle,sql_text,origin,version,enabled,accepted,fixed from dba_sql_plan_baselines
SQL_HANDLE  SQL_TEXT           ORIGIN                   VERSION  ENABLED    ACCEPTED    FIXED
SQL_4313a2ffff308f08    <CLOB>  MANUAL-LOAD 11.2.0.4.0      YES      YES            NO

創建索引:
create index i_employee_id on hr.emp(employee_Id);
再次執行,檢查child_number:測試

select sql_id,child_number,sql_text ,child_Number from v$sql where sql_text like 'select %hr.emp%';
SQL_ID  CHILD_NUMBER    SQL_TEXT    CHILD_NUMBER
76rrg3a06j24n   1   select * from hr.emp where EMPLOYEE_ID=206  1

查看其執行計劃:this

Plan hash value: 3956160932 
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     2 |   266 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| EMP  |     2 |   266 |     2   (0)| 00:00:01 |
-------------------------------------------------------------------------- 
Predicate Information (identified by operation id):
--------------------------------------------------- 
   1 - filter("EMPLOYEE_ID"=206) 
Note
-----
   - SQL plan baseline "SQL_PLAN_464x2zzzm13s8d8a279cc" used for this statement

依舊全表掃描,這是不科學的,理論上是走索引,他給出了說明,走的是SQL_PLAN_464x2zzzm13s8d8a279cc,檢查dba_sql_plan_baselinescode

SQL_HANDLE SQL_TEXT    ORIGIN             VERSION  ENABLED ACCEPTED    FIXED   PLAN_NAME
SQL_4313a2ffff308f08    <CLOB>  MANUAL-LOAD 11.2.0.4.0  YES YES NO  SQL_PLAN_464x2zzzm13s8d8a279cc
SQL_4313a2ffff308f08    <CLOB>  AUTO-CAPTURE    11.2.0.4.0  YES NO  NO  SQL_PLAN_464x2zzzm13s8f5e7e8ee

這裏其實他是捕捉到另外一個執行計劃了,可是,因爲沒啓用,就是全表掃描了,啓用新的執行計劃:orm

declare
tp clob;
begin
tp:=dbms_spm.evolve_sql_plan_baseline(sql_handle=>'SQL_4313a2ffff308f08',plan_name=>'SQL_PLAN_464x2zzzm13s8f5e7e8ee');
end;

再次運行:索引

Plan hash value: 1162342648

---------------------------------------------------------------------------------------------
| Id  | Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |               |     1 |   133 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP           |     1 |   133 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | I_EMPLOYEE_ID |     1 |       |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------

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

   2 - access("EMPLOYEE_ID"=206)

Note
-----
   - dynamic sampling used for this statement (level=2)
   - SQL plan baseline "SQL_PLAN_464x2zzzm13s8f5e7e8ee" used for this statement

好了,走正常的執行計劃了,再次刪除較優的base_line:hash

declare v_ret  varchar2(100);
begin
  v_ret:= dbms_spm.drop_sql_plan_baseline(sql_handle=>'SQL_4313a2ffff308f08',plan_name=>'SQL_PLAN_464x2zzzm13s8f5e7e8ee');
  end  ;

毫無疑問,又走全表掃描了,但dba_hist_sql_plan_baselines裏依舊是生成了的,只是沒有啓用而已;
修改狀態:it

declare
v_ret  varchar2(100);
begin
v_ret := dbms_spm.alter_sql_plan_baseline(
sql_handle=>'SQL_4313a2ffff308f08',
plan_name=>'SQL_PLAN_464x2zzzm13s8d8a279cc',
attribute_name=>'enabled',
attribute_value=>'NO'
);
end;

查看執行計劃,兩個都沒啓用了,這和修改參數(optimizer_use_sql_plan_baselines=false)是同樣的:
Execution Plan

----------------------------------------------------------
Plan hash value: 1162342648 
---------------------------------------------------------------------------------------------
| Id  | Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |               |     1 |   133 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMP           |     1 |   133 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | I_EMPLOYEE_ID |     1 |       |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------- 
Predicate Information (identified by operation id):
--------------------------------------------------- 
   2 - access("EMPLOYEE_ID"=206) 
Note
-----
   - dynamic sampling used for this statement (level=2)
相關文章
相關標籤/搜索