Oracle 固定執行計划-使用SPM(Sql Plan Management)固定執行計划


固定執行計划-使用SPM(Sql Plan Management)固定執行計划

轉載自:http://www.lunar2013.com/2016/01/固定執行計划-使用spm%EF%BC%88sql-plan-management%EF%BC%89固定執行計划.html

.
固定執行計划-使用SQL Tuning Advisor
固定執行計划-手工指定PLAN OUTLINE
固定執行計划-手工指定索引名稱的方式
固定執行計划-使用coe_xfr_sql_profile固定執行計划
固定執行計划-使用SPM(Sql Plan Management)固定執行計划
.

在Oracle 11g前,我們可以借助存儲大綱(Stored Outline)和SQL Profile來幫助我們固定某個SQL語句的執行計划。
11g中,Oracle 提供了SPM(Sql Plan Management)。
通過這個特性,可以考慮讓Oracle自動去判斷某個SQL的新的執行計划是否更加合理(成本更低),只有在新的執行計划比原來的執行計划更好才會被使用,從而保護了執行計划的穩定性和SQL語句的執行效率。
可以考慮手工捕獲和自動捕獲兩種方式,這里我們采用手工捕獲(11.2的缺省設置是非自動捕獲)。
首先查看當前為禁止自動捕獲的狀態:

SYS@lunardb>show parameter optimizer_capture_sql_plan_baselines
 
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_capture_sql_plan_baselines boolean     FALSE
SYS@lunardb>

當前SPM中沒有內容:

LUNAR@lunardb> select signature,sql_handle,plan_name,origin,enabled,accepted,autopurge from dba_sql_plan_baselines;
 
no rows selected
 
Elapsed: 00:00:00.00
LUNAR@lunardb>

手工加載一個SQL到SPM中:

LUNAR@lunardb> declare
   2    l_plans_loaded  PLS_INTEGER;
   3  begin
   4    l_plans_loaded := DBMS_SPM.load_plans_from_cursor_cache(sql_id => '&sql_id' );
   5    DBMS_OUTPUT.put_line( 'Plans Loaded: ' || l_plans_loaded);
   6  END;
   7  /
Enter value for sql_id: bjgduva68mbqm
old   4:   l_plans_loaded := DBMS_SPM.load_plans_from_cursor_cache(sql_id => '&sql_id' );
new   4:   l_plans_loaded := DBMS_SPM.load_plans_from_cursor_cache(sql_id => 'bjgduva68mbqm' );
Plans Loaded: 1
 
PL /SQL procedure successfully completed.
 
Elapsed: 00:00:00.21
LUNAR@lunardb>
LUNAR@lunardb> select signature,sql_handle,plan_name,origin,enabled,accepted,autopurge from dba_sql_plan_baselines;
 
        SIGNATURE SQL_HANDLE                     PLAN_NAME                      ORIGIN         ENA ACC AUT
---------------- ------------------------------ ------------------------------ -------------- --- --- ---
6.5941520220E+17 SQL_0926b6a1f69f6f5c           SQL_PLAN_0k9pqn7v9yvuw02b73393 MANUAL-LOAD    YES YES YES
 
Elapsed: 00:00:00.01
LUNAR@lunardb>

由於上一個測試,我們已經有了正確的執行計划,即:

LUNAR@lunardb> select * from table(dbms_xplan.display_cursor(sql_id=> 'bjgduva68mbqm' )) where plan_table_output  like ( 'Plan hash value%' );
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3241900148
 
Elapsed: 00:00:00.02
LUNAR@lunardb>
LUNAR@lunardb> select SQL_HANDLE, PLAN_NAME, ENABLED, ACCEPTED, SQL_TEXT
   2  from DBA_SQL_PLAN_BASELINES
   3  where ACCEPTED = 'YES'
   4  order by LAST_MODIFIED;
 
SQL_HANDLE                     PLAN_NAME                      ENA ACC SQL_TEXT
------------------------------ ------------------------------ --- --- --------------------------------------------------------------------------------
SQL_0926b6a1f69f6f5c           SQL_PLAN_0k9pqn7v9yvuw02b73393 YES YES select /*+ no_index(lunartest1 idx_lunartest1_n) */ * from lunartest1 where n=1
 
Elapsed: 00:00:00.01
LUNAR@lunardb>

下面,我們裝載指定的執行計划:

LUNAR@lunardb>variable cnt number ;
LUNAR@lunardb> exec :cnt :=dbms_spm.LOAD_PLANS_FROM_CURSOR_CACHE (SQL_ID => '&SQL_ID' ,PLAN_HASH_VALUE => &plan_hash_value, SQL_HANDLE => '&SQL_HANDLE' ) ;
Enter value for sql_id: bjgduva68mbqm
Enter value for plan_hash_value: 1172089107
Enter value for sql_handle: SQL_0926b6a1f69f6f5c
 
PL /SQL procedure successfully completed.
 
Elapsed: 00:00:00.02
LUNAR@lunardb> select signature,sql_handle,plan_name,origin,enabled,accepted,autopurge
   2  from dba_sql_plan_baselines where CREATED>sysdate-1 /48 order by created;
 
              SIGNATURE SQL_HANDLE                     PLAN_NAME                      ORIGIN         ENA ACC AUT
---------------------- ------------------------------ ------------------------------ -------------- --- --- ---
     659415202199990108 SQL_0926b6a1f69f6f5c           SQL_PLAN_0k9pqn7v9yvuw02b73393 MANUAL-LOAD    YES YES YES
 
Elapsed: 00:00:00.00
LUNAR@lunardb>

確認該執行計划的OUTLINE:

LUNAR@lunardb>SELECT extractValue(value(h), '.' ) AS hint
   2  FROM sys.sqlobj$data od, sys.sqlobj$ so,
   3  table(xmlsequence(extract(xmltype(od.comp_data), '/outline_data/hint' ))) h
   4  WHERE so.name = 'SQL_PLAN_0k9pqn7v9yvuw02b73393'
   5  AND so.signature = od.signature
   6  AND so.category = od.category
   7  AND so.obj_type = od.obj_type
   8  AND so.plan_id = od.plan_id;
 
HINT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE( '11.2.0.4' )
DB_VERSION( '11.2.0.4' )
ALL_ROWS
OUTLINE_LEAF(@ "SEL$1" )
INDEX(@ "SEL$1" "LUNARTEST1" @ "SEL$1" ( "LUNARTEST1" . "N" ))
 
6 rows selected.
 
Elapsed: 00:00:00.08
LUNAR@lunardb>

這里看到是我們需要的走索引的outline,詳細的OUTLINE信息如下:

LUNAR@lunardb>SELECT extractValue(value(h), '.' ) AS hint
   2  FROM sys.sqlobj$data od, sys.sqlobj$ so,
   3  table(xmlsequence(extract(xmltype(od.comp_data), '/outline_data/hint' ))) h
   4  WHERE so.signature = '659415202199990108'
   5  AND so.signature = od.signature
   6  AND so.category = od.category
   7  AND so.obj_type = od.obj_type
   8  AND so.plan_id = od.plan_id;
 
HINT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE( '11.2.0.4' )
DB_VERSION( '11.2.0.4' )
ALL_ROWS
OUTLINE_LEAF(@ "SEL$1" )
INDEX(@ "SEL$1" "LUNARTEST1" @ "SEL$1" ( "LUNARTEST1" . "N" ))
END_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE( '11.2.0.4' )
DB_VERSION( '11.2.0.4' )
ALL_ROWS
OUTLINE_LEAF(@ "SEL$1" )
INDEX(@ "SEL$1" "LUNARTEST1" @ "SEL$1" ( "LUNARTEST1" . "N" ))
 
14 rows selected.
 
Elapsed: 00:00:00.10
LUNAR@lunardb>   

現在我們刪除profile以前用coe綁定的sql profile:

LUNAR@lunardb>SELECT * FROM DBA_SQL_PROFILES;
 
NAME                           CATEGORY                                    SIGNATURE SQL_TEXT
------------------------------ ------------------------------ ---------------------- --------------------------------------------------------------------------------
CREATED                                                                     LAST_MODIFIED
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
DESCRIPTION
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TYPE    STATUS   FOR          TASK_ID TASK_EXEC_NAME                      TASK_OBJ_ID      TASK_FND_ID      TASK_REC_ID
------- -------- --- ---------------- ------------------------------ ---------------- ---------------- ----------------
coe_bjgduva68mbqm_3241900148   DEFAULT                            659415202199990108 select /*+ no_index(lunartest1 idx_lunartest1_n) */ * from lunartest1 where n=1
12-JAN-16 11.24.18.000000 AM                                                12-JAN-16 11.40.52.000000 AM
coe bjgduva68mbqm 3241900148 659415202199990108 9900816299026594015
MANUAL  ENABLED  NO
 
 
Elapsed: 00:00:00.01
LUNAR@lunardb>
LUNAR@lunardb> exec dbms_sqltune.drop_sql_profile( 'coe_bjgduva68mbqm_3241900148' );
 
PL /SQL procedure successfully completed.
 
Elapsed: 00:00:00.01
LUNAR@lunardb>SELECT * FROM DBA_SQL_PROFILES;
 
no rows selected
 
Elapsed: 00:00:00.00
LUNAR@lunardb>

再次驗證SPM的執行計划:

LUNAR@lunardb> select * from table(dbms_xplan.DISPLAY_SQL_PLAN_BASELINE( '&sql_handle' , '&PLAN_NAME' ));
Enter value for sql_handle: SQL_0926b6a1f69f6f5c
Enter value for plan_name: SQL_PLAN_0k9pqn7v9yvuw02b73393
old   1: select * from table(dbms_xplan.DISPLAY_SQL_PLAN_BASELINE( '&sql_handle' , '&PLAN_NAME' ))
new   1: select * from table(dbms_xplan.DISPLAY_SQL_PLAN_BASELINE( 'SQL_0926b6a1f69f6f5c' , 'SQL_PLAN_0k9pqn7v9yvuw02b73393' ))
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------
SQL handle: SQL_0926b6a1f69f6f5c
SQL text: select /*+ no_index(lunartest1 idx_lunartest1_n) */ * from lunartest1
           where n=1
--------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------
Plan name: SQL_PLAN_0k9pqn7v9yvuw02b73393         Plan id : 45560723
Enabled: YES     Fixed: NO      Accepted: YES     Origin: MANUAL-LOAD
--------------------------------------------------------------------------------
 
Plan hash value: 3241900148
 
-------------------------------------------------------------------------------------
| Id  | Operation        | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |                  |     1 |     4 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| IDX_LUNARTEST1_N |     1 |     4 |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id ):
---------------------------------------------------
 
    1 - access( "N" =1)
 
25 rows selected.
 
Elapsed: 00:00:00.16
LUNAR@lunardb>

執行SQL,發現SPM可以固定執行計划,使用了我們期待的:

LUNAR@lunardb> set autotrace traceo exp stat
LUNAR@lunardb> select /*+ no_index(lunartest1 idx_lunartest1_n) */ * from lunartest1 where n=1;
 
Elapsed: 00:00:00.13
 
Execution Plan
----------------------------------------------------------
Plan hash value: 3241900148
 
-------------------------------------------------------------------------------------
| Id  | Operation        | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |                  |     1 |     4 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| IDX_LUNARTEST1_N |     1 |     4 |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id ):
---------------------------------------------------
 
    1 - access( "N" =1)
 
Note
-----
    - SQL plan baseline "SQL_PLAN_0k9pqn7v9yvuw02b73393" used for this statement
 
 
Statistics
----------------------------------------------------------
          59  recursive calls
          52  db block gets
          36  consistent gets
           1  physical reads
       15312  redo size
         519  bytes sent via SQL*Net to client
         523  bytes received via SQL*Net from client
           2  SQL*Net roundtrips to /from client
           0  sorts (memory)
           0  sorts (disk)
           1  rows processed
 
LUNAR@lunardb>

這里看到已經使用了SPM中的SQL Profile:SQL_PLAN_0k9pqn7v9yvuw02b73393
總結:
這里已經使用了我們的SPM(SQL_PLAN_0k9pqn7v9yvuw02b73393)固定了執行計划,sql使用了索引
說明SPM綁定執行計划的方式比hint的優先級高


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM