原貼地址:http://www.anbob.com/archives/1551.html
oracle 11g BaseLine(基線)指定application中不可修改sql的執行計劃
11G前有sql profile、outline可以穩定執行計劃,但有些文檔中指出有時outline指定了但也有要能走新的執行計劃,所以11g的BASELINE是OUTLINE的改進版。一般應用在版本升級或穩定特定SQL的執行計劃,也可以修改指定SQL的執行計劃,當OUTLINE與BASELINE有同時指定時BASELINE有優先權。
下面就演示一種如果某SQL是寫在應用程序中無法修改的情況下用BASELINE指定SQL的執行計劃
版本11203
system@ANBOB> conn anbob/anbob Connected. --好比下面這條sql就是寫在應用中的,走了索引 anbob@ANBOB> select /*+index(obj) */segment_name,bytes,segment_type,object_id 2 from obj,myseg where obj.object_name=myseg.segment_name and object_type=myseg.segment_type and obj.owner='ANBOB'; SEGMENT_NAME BYTES SEGMENT_TYPE OBJECT_ID ------------------ ----------------------- ------------ TEST 65536 TABLE 77106 OBJ 9437184 TABLE 77212 anbob@ANBOB> select sql_id,sql_text from v$sql where sql_text like '%index(obj)%'; SQL_ID ------------- SQL_TEXT ---------------------------------------------------------------------------------------------------- 3gxpzgmqr0s2m select /*+index(obj) */segment_name,bytes,segment_type,object_id from obj,myseg where obj.object_na me=myseg.segment_name and object_type=myseg.segment_type and obj.owner='ANBOB' dwy655m5vbbuv select sql_id,sql_text from v$sql where sql_text like '%index(obj)%' anbob@ANBOB> select * from table(dbms_xplan.display_cursor('3gxpzgmqr0s2m')); PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------- SQL_ID 3gxpzgmqr0s2m, child number 0 ------------------------------------- select /*+index(obj) */segment_name,bytes,segment_type,object_id from obj,myseg where obj.object_name=myseg.segment_name and object_type=myseg.segment_type and obj.owner='ANBOB' Plan hash value: 542643170 ------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 2000 (100)| | |* 1 | HASH JOIN | | 6 | 384 | 2000 (1)| 00:00:24 | | 2 | TABLE ACCESS FULL | MYSEG | 6 | 114 | 3 (0)| 00:00:01 | |* 3 | TABLE ACCESS BY INDEX ROWID| OBJ | 2417 | 106K| 1997 (1)| 00:00:24 | | 4 | INDEX FULL SCAN | IDX_OBJ_ID | 72505 | | 329 (1)| 00:00:04 | ------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("OBJ"."OBJECT_NAME"="MYSEG"."SEGMENT_NAME" AND "OBJECT_TYPE"="MYSEG"."SEGMENT_TYPE") 3 - filter("OBJ"."OWNER"='ANBOB') baseline 加載有兩種方式 1,從libary cache加載 DESC dbms_spm 有一這函數LOAD_PLANS_FROM_CURSOR_CACHE 2,自動加載 在session級設置optimizer_capture_sql_plan_baseline=true 執行兩次相同sql,那條sql 計劃基線就創建了 --下面用第一種方法,用DBMS_SPM Package的一個function FUNCTION LOAD_PLANS_FROM_CURSOR_CACHE RETURNS BINARY_INTEGER Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- SQL_ID VARCHAR2 IN PLAN_HASH_VALUE NUMBER IN DEFAULT FIXED VARCHAR2 IN DEFAULT ENABLED VARCHAR2 IN DEFAULT anbob@ANBOB> declare 2 v_rec BINARY_INTEGER; 3 begin 4 v_rec:=dbms_spm.LOAD_PLANS_FROM_CURSOR_CACHE(sql_id=>'3gxpzgmqr0s2m'); 5 end; 6 / PL/SQL procedure successfully completed. anbob@ANBOB> set autot trace exp stat anbob@ANBOB> select /*+index(obj) */segment_name,bytes,segment_type,object_id 2 from obj,myseg where obj.object_name=myseg.segment_name and object_type=myseg.segment_type and obj.owner='ANBOB'; Execution Plan ---------------------------------------------------------- Plan hash value: 542643170 ------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 6 | 384 | 2000 (1)| 00:00:25 | |* 1 | HASH JOIN | | 6 | 384 | 2000 (1)| 00:00:25 | | 2 | TABLE ACCESS FULL | MYSEG | 6 | 114 | 3 (0)| 00:00:01 | |* 3 | TABLE ACCESS BY INDEX ROWID| OBJ | 2417 | 106K| 1997 (1)| 00:00:24 | | 4 | INDEX FULL SCAN | IDX_OBJ_ID | 72505 | | 329 (1)| 00:00:04 | ------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("OBJ"."OBJECT_NAME"="MYSEG"."SEGMENT_NAME" AND "OBJECT_TYPE"="MYSEG"."SEGMENT_TYPE") 3 - filter("OBJ"."OWNER"='ANBOB') Note ----- - SQL plan baseline "SQL_PLAN_36nsrk905n05r7051a058" used for this statement Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 1999 consistent gets 0 physical reads 0 redo size 688 bytes sent via SQL*Net to client 419 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 2 rows processed --查詢存在的基線 anbob@ANBOB> select sql_handle,sql_text,plan_name from dba_sql_plan_baselines; SQL_HANDLE ------------------------------ SQL_TEXT -------------------------------------------------------------------------------- PLAN_NAME ------------------------------ SQL_33531792405a00b7 select /*+index(obj) */segment_name,bytes,segment_type,object_id from obj,myseg where obj.object_name=myseg.segment_name and object_type=myseg.se gment_type and obj.owner='ANBOB' SQL_PLAN_36nsrk905n05r7051a058 確定了第一個的執行計劃,下面想試一下如果obj表full table scan 效率是不是更高,如果更高就替換掉上面的執行計劃。 anbob@ANBOB> select /*+full(obj) */segment_name,bytes,segment_type,object_id 2 from obj,myseg where obj.object_name=myseg.segment_name and object_type=myseg.segment_type and obj.owner='ANBOB'; SEGMENT_NAME BYTES --------------------------------------------------------------------------------- ---------- SEGMENT_TYPE OBJECT_ID ------------------ ---------- TEST 65536 TABLE 77106 OBJ 9437184 TABLE 77212 anbob@ANBOB> select sql_id,sql_text from v$sql where sql_text like '%full(obj)%'; SQL_ID ------------- SQL_TEXT ---------------------------------------------------------------------------------------------------- fmkssffqd93vv select sql_id,sql_text from v$sql where sql_text like '%full(obj)%' grsp8m270rmum select /*+full(obj) */segment_name,bytes,segment_type,object_id from obj,myseg where obj.object_nam e=myseg.segment_name and object_type=myseg.segment_type and obj.owner='ANBOB' anbob@ANBOB> select * from table(dbms_xplan.display_cursor('grsp8m270rmum')); PLAN_TABLE_OUTPUT ---------------------------------------------------------------------------------------------------- SQL_ID grsp8m270rmum, child number 0 ------------------------------------- select /*+full(obj) */segment_name,bytes,segment_type,object_id from obj,myseg where obj.object_name=myseg.segment_name and object_type=myseg.segment_type and obj.owner='ANBOB' Plan hash value: 98466713 ---------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 293 (100)| | |* 1 | HASH JOIN | | 6 | 384 | 293 (1)| 00:00:04 | | 2 | TABLE ACCESS FULL| MYSEG | 6 | 114 | 3 (0)| 00:00:01 | |* 3 | TABLE ACCESS FULL| OBJ | 2417 | 106K| 290 (1)| 00:00:04 | ---------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("OBJ"."OBJECT_NAME"="MYSEG"."SEGMENT_NAME" AND "OBJECT_TYPE"="MYSEG"."SEGMENT_TYPE") 3 - filter("OBJ"."OWNER"='ANBOB') 24 rows selected. --替換方法是根據sql handle再增加FULL TALE SCAN的執行計劃(當存在兩個時,CBO會選擇COST較小的執行計劃),然後再根據sql handle和plan name 刪掉走索引的執行計劃 anbob@ANBOB> l 1 declare 2 v_rec binary_integer; 3 begin 4 v_rec:=dbms_spm.LOAD_PLANS_FROM_CURSOR_CACHE(sql_id=>'grsp8m270rmum', 5 sql_handle=>'SQL_33531792405a00b7'); 6* end; anbob@ANBOB> / PL/SQL procedure successfully completed. anbob@ANBOB> select sql_handle,sql_text,plan_name from dba_sql_plan_baselines; SQL_HANDLE ------------------------------ SQL_TEXT -------------------------------------------------------------------------------- PLAN_NAME ------------------------------ SQL_33531792405a00b7 select /*+index(obj) */segment_name,bytes,segment_type,object_id from obj,myseg where obj.object_name=myseg.segment_name and object_type=myseg.se gment_type and obj.owner='ANBOB' SQL_PLAN_36nsrk905n05r5b6a4a48 SQL_33531792405a00b7 select /*+index(obj) */segment_name,bytes,segment_type,object_id from obj,myseg where obj.object_name=myseg.segment_name and object_type=myseg.se gment_type and obj.owner='ANBOB' SQL_PLAN_36nsrk905n05r7051a058 用dbms_spw包刪掉之前走索引的執行計劃 FUNCTION DROP_SQL_PLAN_BASELINE RETURNS BINARY_INTEGER Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- SQL_HANDLE VARCHAR2 IN DEFAULT PLAN_NAME VARCHAR2 IN DEFAULT anbob@ANBOB> declare 2 v_rec binary_integer; 3 begin 4 v_rec:=dbms_spm.drop_sql_plan_baseline( 5 sql_handle=>'SQL_33531792405a00b7', 6 plan_name=>'SQL_PLAN_36nsrk905n05r7051a058'); 7 end; 8 / PL/SQL procedure successfully completed. anbob@ANBOB> select sql_handle,sql_text,plan_name from dba_sql_plan_baselines; SQL_HANDLE ------------------------------ SQL_TEXT -------------------------------------------------------------------------------- PLAN_NAME ------------------------------ SQL_33531792405a00b7 select /*+index(obj) */segment_name,bytes,segment_type,object_id from obj,myseg where obj.object_name=myseg.segment_name and object_type=myseg.se gment_type and obj.owner='ANBOB' SQL_PLAN_36nsrk905n05r5b6a4a48 anbob@ANBOB> set autot trace exp stat anbob@ANBOB> select /*+index(obj) */segment_name,bytes,segment_type,object_id 2 from obj,myseg where obj.object_name=myseg.segment_name and object_type=myseg.segment_type 3* and obj.owner='ANBOB' anbob@ANBOB> / Execution Plan ---------------------------------------------------------- Plan hash value: 98466713 ---------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 6 | 384 | 293 (1)| 00:00:04 | |* 1 | HASH JOIN | | 6 | 384 | 293 (1)| 00:00:04 | | 2 | TABLE ACCESS FULL| MYSEG | 6 | 114 | 3 (0)| 00:00:01 | |* 3 | TABLE ACCESS FULL| OBJ | 2417 | 106K| 290 (1)| 00:00:04 | ---------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("OBJ"."OBJECT_NAME"="MYSEG"."SEGMENT_NAME" AND "OBJECT_TYPE"="MYSEG"."SEGMENT_TYPE") 3 - filter("OBJ"."OWNER"='ANBOB') Note ----- - SQL plan baseline "SQL_PLAN_36nsrk905n05r5b6a4a48" used for this statement Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 1040 consistent gets 0 physical reads 0 redo size 688 bytes sent via SQL*Net to client 419 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 2 rows processed ok,指定了 note: 指定sql 執行計劃歷史方法 Oracle 8: hint Oracle 8i&9: stored outline Oracle 10: sql profile Oracle 11: sql plan manangement SQL Management Base SMB: 字典表裏保存的執行計劃的總稱,包括Plan History,SQL Plan Baseline和SQL profile,存儲在sysaux tablespace中