固定執行計划-使用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的優先級高