SQL Profiles-PartII--老熊
在上一篇《SQL Profiles-Part I》,我向大家介紹了什麼是SQL Profiles及其作用,如何使用SQL Tuning Advisor來生成SQL Profile,以及生成的SQL Profile產生的Hint。同時也介紹了SQL的signature。那麼在今天,將向大家介紹如何手工建立SQL Profiles(即不透過SQL Tuning Advisor)來達成2個目的:
- 鎖定或者說穩定SQL執行計劃。
- 在不能修改應用的SQL的情況下,來改變或者說是強制使SQL使用我們指定的執行計劃,即使原始的SQL包含了Hints。
那麼,這裡最關鍵的一點是,如何來手工建立SQL Profiles?
答案是,正如上一篇中有朋友的留言,使用DBMS_SQLTUNE.IMPORT_SQL_PROFILE過程。
- SQL> desc dbms_sqltune
- ...
- PROCEDURE IMPORT_SQL_PROFILE
- 引數名稱 型別 輸入/輸出預設值?
- ------------------------------ ----------------------- ------ --------
- SQL_TEXT CLOB IN
- PROFILE SQLPROF_ATTR IN
- NAME VARCHAR2 IN DEFAULT
- DESCRIPTION VARCHAR2 IN DEFAULT
- CATEGORY VARCHAR2 IN DEFAULT
- VALIDATE BOOLEAN IN DEFAULT
- REPLACE BOOLEAN IN DEFAULT
- FORCE_MATCH BOOLEAN IN DEFAULT
- ...
這個過程其名字與實際功能有所差異,其實可以理解為CREATE OR REPLACE SQL_PROFILE。過程中的PROFILE引數為SYS.SQLPROF_ATTR,這種型別其實就是VARCHAR2的集合型別(COLLECTION):
- SQL> select text from dba_source where name='SQLPROF_ATTR' and owner='SYS';
- TYPE sqlprof_attr
- AS VARRAY(2000) of VARCHAR2(500)
下面我們就用這個過程來建立SQL PROFILE:
為避免干擾,將上一篇測試中生成的SQL Profile刪除掉,同時恢復T1表的統計資訊中的錶行數:
- SQL> exec dbms_sqltune.drop_sql_profile('SYS_SQLPROF_014b39f084c88000');
- PL/SQL 過程已成功完成。
- SQL> exec dbms_stats.set_table_stats('TEST1','T1',numrows=>49953);
- PL/SQL 過程已成功完成。
現在我們手工建立一個SQL Profile:
- SQL> declare
- 2 v_hints sys.sqlprof_attr;
- 3 begin
- 4 v_hints:=sys.sqlprof_attr('USE_NL(T1 T2)','INDEX(T2)');
- 5 dbms_sqltune.import_sql_profile('select t1.*,t2.owner from t1,t2 where t1.object_name like ''%T1%'' and t1.object_id=t2.object_id',
- 6 v_hints,'SQLPROFILE_NAME1',force_match=>true);
- 7 end;
- 8 /
- PL/SQL 過程已成功完成。
- SQL> select attr_val from dba_sql_profiles a, sys.sqlprof$attr b
- 2 where a.signature = b.signature
- 3 and a.name='SQLPROFILE_NAME1';
- ATTR_VAL
- ----------------------------------------
- USE_NL(T1 T2)
- INDEX(T2)
下面執行SQL Profiles對應的SQL:
- SQL> select t1.*,t2.owner
- 2 from t1,t2
- 3 where t1.object_name like '%T1%'
- 4 and t1.object_id=t2.object_id;
- 已選擇29行。
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 1838229974
- ---------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- ---------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 2498 | 99920 | 219 (4)| 00:00:03 |
- |* 1 | HASH JOIN | | 2498 | 99920 | 219 (4)| 00:00:03 |
- |* 2 | TABLE ACCESS FULL| T1 | 2498 | 72442 | 59 (6)| 00:00:01 |
- | 3 | TABLE ACCESS FULL| T2 | 49954 | 536K| 159 (2)| 00:00:02 |
- ---------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 1 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
- 2 - filter("T1"."OBJECT_NAME" LIKE '%T1%')
- Note
- -----
- - SQL profile "SQLPROFILE_NAME1" used for this statement
- 統計資訊
- ----------------------------------------------------------
- 0 recursive calls
- 0 db block gets
- 933 consistent gets
可以看到,SQL使用了SQL Profile,不過沒有達到我們預期的效果。
看起來是SQL Profile使用的Hints有問題。我們重新設定SQL Profile的Hints,在Hints中加上“Query Block Name”。這一次在執行IMPORT_SQL_PROFILE過程時,將REPLACE引數設定為TRUE,以替換現有的SQL Profile:
- SQL> declare
- 2 v_hints sys.sqlprof_attr;
- 3 begin
- 4 v_hints:=sys.sqlprof_attr('USE_NL(T1@SEL$1 T2@SEL$1)','INDEX(T2@SEL$1)');
- 5 dbms_sqltune.import_sql_profile('select t1.*,t2.owner from t1,t2 where t1.object_name like ''%T1%'' and t1.object_id=t2.object_id',
- 6 v_hints,'SQLPROFILE_NAME1',force_match=>true,replace=>true);
- 7 end;
- 8 /
- PL/SQL 過程已成功完成。
- SQL> select attr_val from dba_sql_profiles a, sys.sqlprof$attr b
- 2 where a.signature = b.signature
- 3 and a.name='SQLPROFILE_NAME1';
- ATTR_VAL
- ----------------------------------------
- USE_NL(T1@SEL$1 T2@SEL$1)
- INDEX(T2@SEL$1)
再次執行下面的SQL:
- SQL> select t1.*,t2.owner
- 2 from t1,t2
- 3 where t1.object_name like '%T1%'
- 4 and t1.object_id=t2.object_id;
- 已選擇29行。
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 3787413387
- --------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- --------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 2498 | 99920 | 5061 (1)| 00:01:01 |
- | 1 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 11 | 2 (0)| 00:00:01 |
- | 2 | NESTED LOOPS | | 2498 | 99920 | 5061 (1)| 00:01:01 |
- |* 3 | TABLE ACCESS FULL | T1 | 2498 | 72442 | 59 (6)| 00:00:01 |
- |* 4 | INDEX RANGE SCAN | T2_IDX | 1 | | 1 (0)| 00:00:01 |
- --------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 3 - filter("T1"."OBJECT_NAME" LIKE '%T1%')
- 4 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
- Note
- -----
- - SQL profile "SQLPROFILE_NAME1" used for this statement
- 統計資訊
- ----------------------------------------------------------
- 0 recursive calls
- 0 db block gets
- 294 consistent gets
這一次達到了預期的效果。看起來在SQL Profiles中對Hints還有一定的要求。
那麼我們再一次手工修改T1表的統計資訊,看看結果如何:
- SQL> exec dbms_stats.set_table_stats('TEST1','T1',numrows=>5000000);
- PL/SQL 過程已成功完成。
- SQL> select t1.*,t2.owner
- 2 from t1,t2
- 3 where t1.object_name like '%T1%'
- 4 and t1.object_id=t2.object_id;
- 已選擇29行。
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 3787413387
- --------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- --------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 250K| 9765K| 500K (1)| 01:40:12 |
- | 1 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 11 | 2 (0)| 00:00:01 |
- | 2 | NESTED LOOPS | | 250K| 9765K| 500K (1)| 01:40:12 |
- |* 3 | TABLE ACCESS FULL | T1 | 250K| 7080K| 288 (81)| 00:00:04 |
- |* 4 | INDEX RANGE SCAN | T2_IDX | 1 | | 1 (0)| 00:00:01 |
- --------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 3 - filter("T1"."OBJECT_NAME" LIKE '%T1%')
- 4 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
- Note
- -----
- - SQL profile "SQLPROFILE_NAME1" used for this statement
- 統計資訊
- ----------------------------------------------------------
- 0 recursive calls
- 0 db block gets
- 294 consistent gets
可以看到,Oracle最佳化器評估表T1經過Like條件過濾後返回的行數雖然很大,但是這裡的執行計劃仍然與未修改統計資訊之前一樣,使用range scan+ nested loop join。
透過以上的測試,我們明白了DBMS_SQLTUNE.IMPORT_SQL_PROFILE的使用,同時也驗證了這種方式的有效性,SQL Profiles能夠像Outlines一樣,能夠穩定SQL的執行計劃。
接下來我們需要完成兩個任務。
任務一:對現有的SQL穩定其執行計劃。
這裡的問題是:穩定一條SQL語句的Hints從哪裡來?簡單的sql,沒問題,我們可以手工構造,但是複雜的SQL,手工構造相對比較複雜,同時手工構造的Hints不一定能夠保證SQL的執行計劃就會穩定。從10g開始,v$sql_plan中就包括了SQL語句OUTLINE資料,也就是穩定執行計劃的Hints。從下面可以看到:
- SQL> select t1.*,t2.owner
- 2 from t1,t2
- 3 where t1.object_name like '%T1%'
- 4 and t1.object_id=t2.object_id;
- 已選擇29行。
- SQL> select * from table(dbms_xplan.display_cursor(null,null,'outline'));
- PLAN_TABLE_OUTPUT
- ----------------------------------------------------------------------------------------
- SQL_ID 6m45w7r0xgdfj, child number 0
- -------------------------------------
- select t1.*,t2.owner from t1,t2 where t1.object_name like '%T1%'
- and t1.object_id=t2.object_id
- Plan hash value: 3787413387
- --------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- --------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | | | 5061 (100)| |
- | 1 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 11 | 2 (0)| 00:00:01 |
- | 2 | NESTED LOOPS | | 2498 | 99920 | 5061 (1)| 00:01:01 |
- |* 3 | TABLE ACCESS FULL | T1 | 2498 | 72442 | 59 (6)| 00:00:01 |
- |* 4 | INDEX RANGE SCAN | T2_IDX | 1 | | 1 (0)| 00:00:01 |
- --------------------------------------------------------------------------------------
- Outline Data
- -------------
- /*+
- BEGIN_OUTLINE_DATA
- IGNORE_OPTIM_EMBEDDED_HINTS
- OPTIMIZER_FEATURES_ENABLE('10.2.0.1')
- ALL_ROWS
- OUTLINE_LEAF(@"SEL$1")
- FULL(@"SEL$1" "T1"@"SEL$1")
- INDEX(@"SEL$1" "T2"@"SEL$1" ("T2"."OBJECT_ID"))
- LEADING(@"SEL$1" "T1"@"SEL$1" "T2"@"SEL$1")
- USE_NL(@"SEL$1" "T2"@"SEL$1")
- END_OUTLINE_DATA
- */
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 3 - filter("T1"."OBJECT_NAME" LIKE '%T1%')
- 4 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
- Note
- -----
- - SQL profile "SQLPROFILE_NAME1" used for this statement
上面所顯示的“Outline Data”即是我們穩定SQL執行計劃需要的Hints(我們甚至可以將這些Hints直接寫到我們的SQL中)。對需要穩定執行計劃的SQL,我們所要做的就是如前面所示,將Hints與SQL文字一起建立一個SQL Profile。這裡不得不提到一個SQL指令碼,來自MOS。”SQLT (SQLTXPLAIN) – Tool that helps to diagnose SQL statements performing poorly [ID 215187.1]“,在這篇文章中,可以下載到sqlt.zip,這個壓縮檔案內有一個檔案:coe_xfr_sql_profile.sql。這個指令碼可以用於從shared pool、awr中提取指定的SQL ID的Outline Data並建立SQL Profile。下面是示例:
- SQL> select /*+ proftest1 */ t1.*,t2.owner
- 2 from t1,t2
- 3 where t1.object_name like '%T1%'
- 4 and t1.object_id=t2.object_id;
- --在shared pool中查詢剛剛執行的SQL,其ID為b4zvp712np1bp--
- SQL> @coe_xfr_sql_profile.sql
- Parameter 1:
- SQL_ID (required)
- 輸入 1 的值: b4zvp712np1bp
- PLAN_HASH_VALUE AVG_ET_SECS
- --------------- -----------
- 2959412835 .112
- Parameter 2:
- PLAN_HASH_VALUE (required)
- 輸入 2 的值: 2959412835
- Values passed:
- ~~~~~~~~~~~~~
- SQL_ID : "b4zvp712np1bp"
- PLAN_HASH_VALUE: "2959412835"
- Execute coe_xfr_sql_profile_b4zvp712np1bp_2959412835.sql
- on TARGET system in order to create a custom SQL Profile
- with plan 2959412835 linked to adjusted sql_text.
- COE_XFR_SQL_PROFILE completed.
- SQL>@coe_xfr_sql_profile_b4zvp712np1bp_2959412835.sql
- PL/SQL 過程已成功完成。
- SQL>WHENEVER SQLERROR CONTINUE
- SQL>SET ECHO OFF;
- SIGNATURE
- ---------------------
- 6058051510930011685
- ... manual custom SQL Profile has been created
- COE_XFR_SQL_PROFILE_b4zvp712np1bp_2959412835 completed
- SQL>select attr_val from sys.sqlprof$attr where signature=6058051510930011685;
- ATTR_VAL
- --------------------------------------------------
- BEGIN_OUTLINE_DATA
- IGNORE_OPTIM_EMBEDDED_HINTS
- OPTIMIZER_FEATURES_ENABLE('10.2.0.1')
- ALL_ROWS
- OUTLINE_LEAF(@"SEL$1")
- FULL(@"SEL$1" "T2"@"SEL$1")
- FULL(@"SEL$1" "T1"@"SEL$1")
- LEADING(@"SEL$1" "T2"@"SEL$1" "T1"@"SEL$1")
- USE_HASH(@"SEL$1" "T1"@"SEL$1")
- END_OUTLINE_DATA
coe_xfr_sql_profile.sql這個指令碼首先要求輸入sql id,然後從shared pool、awr中獲取sql執行的各個執行計劃的統計資訊(執行計劃不穩定的SQL通常會有多個不同的執行計劃),然後輸入你認為是正確的、需要穩定的執行計劃的hash value,指令碼就會生成另一個指令碼,這裡為coe_xfr_sql_profile_b4zvp712np1bp_2959412835.sql,然後執行這個指令碼,就會建立出穩定執行計劃所需要的SQL Profile,SQL Profile的名字為:coe+sql_id+plan_hash_value,這裡為coe_b4zvp712np1bp_2959412835。注意,這裡建立的SQL Profile,force match預設為FALSE,我們可以手工修改指令碼將其改為TRUE,同時我們也可以按意願來修改生成的指令碼的其他內容。
除了上面提到的指令碼,這個BLOG裡面也有許多與SQL Profiles相關的指令碼。其中create_sql_profile.sql可完成類似的功能,只不過功能相對簡單,只能從shared pool中生成SQL Profile,因此也更方便。
任務二:在不能修改SQL的情況下改變並固定SQL的執行計劃,即使原始的SQL使用了Hints。
常常遇到這樣的情況,SQL語句其執行計劃有問題,或者是SQL使用了錯誤的Hints(比如 /*+ RULE */)導致SQL效能較差,但是應用又不能修改或者時間內不能修改,那麼我們怎麼來改變SQL的執行計劃呢。有3種辦法,一種是調整統計資訊,這個不建議使用,因為比較複雜、不穩定可靠(統計資訊可能會重新收集),影響面廣(會影響其他訪問此物件的SQL)。第二種是使用OUTLINE,這種方法比較複雜。第三種就是我們今天要介紹的使用SQL Profiles了。
使用SQL Profiles來改變SQL的執行計劃,其本質上就是使用Hints來改變SQL的執行計劃。對於簡單的SQL,我們同樣可以像前面一樣手工構造Hints然後再使用DBMS_SQLTUNE.IMPORT_SQL_PROFILE來實現。但是這種方法還是略顯煩瑣。那麼通常的方法就是”乾坤大挪移“了:
- 取得原始SQL的文字(如有可能還包括sql id)
- 構造一個與原始SQL在邏輯上、結構上完全相同的SQL。這裡強制邏輯上和結構上相同,SQL解析的使用者名稱、SQL中引用物件的使用者名稱甚至是一些predicate條件都可以不同。當然能夠與原始SQL完全一樣就更省事。
- 執行我們構造的SQL,並取得構造的SQL的Outline Data。
- 使用原始SQL的文字和構造的SQL的Outline Data建立SQL Profile。
下面我們來演示一下整個過程。我們這裡要修改執行計劃的SQL是:
- select /*+ orig_sql full(t1) full(t2) use_hash(t1 t2) */ t1.*,t2.owner
- from t1,t2
- where t1.object_name like '%T1%'
- and t1.object_id=t2.object_id;
我們首先需要執行這一條SQL,然後取得的SQL ID為gmvb9bp7f9kqd:
- SQL> select /*+ orig_sql full(t1) full(t2) use_hash(t1 t2) */ t1.*,t2.owner
- 2 from t1,t2
- 3 where t1.object_name like '%T1%'
- 4 and t1.object_id=t2.object_id;
- 已選擇29行。
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 2959412835
- -----------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
- -----------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 250K| 9765K| | 998 (25)| 00:00:12 |
- |* 1 | HASH JOIN | | 250K| 9765K| 1128K| 998 (25)| 00:00:12 |
- | 2 | TABLE ACCESS FULL| T2 | 49954 | 536K| | 159 (2)| 00:00:02 |
- |* 3 | TABLE ACCESS FULL| T1 | 250K| 7080K| | 288 (81)| 00:00:04 |
- -----------------------------------------------------------------------------------
然後我們構造一條SQL,讓這條SQL按我們希望的執行計劃執行,構造的SQL其ID為cymak300cycmd:
- SQL> select /*+ modify_sql index(t1) use_nl(t1 t2) */ t1.*,t2.owner
- 2 from t1,t2
- 3 where t1.object_name like '%T1%'
- 4 and t1.object_id=t2.object_id;
- 已選擇29行。
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 3787413387
- --------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- --------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 250K| 9765K| 500K (1)| 01:40:12 |
- | 1 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 11 | 2 (0)| 00:00:01 |
- | 2 | NESTED LOOPS | | 250K| 9765K| 500K (1)| 01:40:12 |
- |* 3 | TABLE ACCESS FULL | T1 | 250K| 7080K| 288 (81)| 00:00:04 |
- |* 4 | INDEX RANGE SCAN | T2_IDX | 1 | | 1 (0)| 00:00:01 |
- --------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 3 - filter("T1"."OBJECT_NAME" LIKE '%T1%')
- 4 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
然後使用coe_xfr_sql_profile.sql指令碼來提取我們構造的SQL的Outline Data,生成的結果為coe_xfr_sql_profile_cymak300cycmd_3787413387.sql,開啟結果檔案,可以看到有這麼一段:
- h := SYS.SQLPROF_ATTR(
- q'[BEGIN_OUTLINE_DATA]',
- q'[IGNORE_OPTIM_EMBEDDED_HINTS]',
- q'[OPTIMIZER_FEATURES_ENABLE('10.2.0.1')]',
- q'[ALL_ROWS]',
- q'[OUTLINE_LEAF(@"SEL$1")]',
- q'[FULL(@"SEL$1" "T1"@"SEL$1")]',
- q'[INDEX(@"SEL$1" "T2"@"SEL$1" ("T2"."OBJECT_ID"))]',
- q'[LEADING(@"SEL$1" "T1"@"SEL$1" "T2"@"SEL$1")]',
- q'[USE_NL(@"SEL$1" "T2"@"SEL$1")]',
- q'[END_OUTLINE_DATA]');
再針對gmvb9bp7f9kqd使用coe_xfr_sql_profile.sql,生成的結果檔案為coe_xfr_sql_profile_gmvb9bp7f9kqd_2959412835.sql。手工修改這個檔案,將裡面h := SYS.SQLPROF_ATTR…那一段替換成我們之前得到的那一段。這一次我們將這個檔案中的force_match從FALSE改成TRUE。
最後我們執行coe_xfr_sql_profile_gmvb9bp7f9kqd_2959412835.sql這個指令碼檔案:
- SQL>@coe_xfr_sql_profile_gmvb9bp7f9kqd_2959412835.sql
- PL/SQL 過程已成功完成。
- SQL>WHENEVER SQLERROR CONTINUE
- SQL>SET ECHO OFF;
- SIGNATURE
- ---------------------
- 15409905709853673912
- ... manual custom SQL Profile has been created
- COE_XFR_SQL_PROFILE_gmvb9bp7f9kqd_2959412835 completed
這樣就完成了我們所需要的SQL Profile的建立。下面再看看原來的SQL執行情況(這裡我故意將like條件改了一下,以檢視force match是否起作用):
- SQL>select /*+ orig_sql full(t1) full(t2) use_hash(t1 t2) */ t1.*,t2.owner
- 2 from t1,t2
- 3 where t1.object_name like '%T2%'
- 4 and t1.object_id=t2.object_id;
- 已選擇77行。
- 執行計劃
- ----------------------------------------------------------
- Plan hash value: 3787413387
- --------------------------------------------------------------------------------------
- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
- --------------------------------------------------------------------------------------
- | 0 | SELECT STATEMENT | | 250K| 9765K| 500K (1)| 01:40:12 |
- | 1 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 11 | 2 (0)| 00:00:01 |
- | 2 | NESTED LOOPS | | 250K| 9765K| 500K (1)| 01:40:12 |
- |* 3 | TABLE ACCESS FULL | T1 | 250K| 7080K| 288 (81)| 00:00:04 |
- |* 4 | INDEX RANGE SCAN | T2_IDX | 1 | | 1 (0)| 00:00:01 |
- --------------------------------------------------------------------------------------
- Predicate Information (identified by operation id):
- ---------------------------------------------------
- 3 - filter("T1"."OBJECT_NAME" LIKE '%T2%')
- 4 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID")
- Note
- -----
- - SQL profile "coe_gmvb9bp7f9kqd_2959412835" used for this statement
- 統計資訊
- ----------------------------------------------------------
- 0 recursive calls
- 0 db block gets
- 363 consistent gets
可以看到SQL Profile起作用了。
最後一步,生成SQL Profile時稍顯複雜,不過我們可以修改之前提到的create_sql_profile.sql檔案來達到同樣的目的,只不過前幾個步驟仍然是不可省略的。將裡面的程式碼:
- select extractvalue(value(d), '/hint') as outline_hints bulk collect
- into ar_profile_hints
- from xmltable('/*/outline_data/hint' passing
- (select xmltype(other_xml) as xmlval
- from v$sql_plan
- where sql_id = '&&sql_id'
- and child_number = &&child_no
- and other_xml is not null)) d;
改為
- select extractvalue(value(d), '/hint') as outline_hints bulk collect
- into ar_profile_hints
- from xmltable('/*/outline_data/hint' passing
- (select xmltype(other_xml) as xmlval
- from v$sql_plan
- where sql_id = '&&modi_sql_id'
- and child_number = &&modi_child_no
- and other_xml is not null)) d;
注意這裡modi_sql_id和modi_child_no為我們構造的SQL執行後的id及child_number。同時這2個變數在檔案前面需要定義,此處不再細述。
小結:本文承接上一篇,介紹瞭如何利用SQL Profile來穩定執行計劃;如何利用SQL Profile來改變SQL的執行計劃。對於SQL Profiles來說,不屬於任何一個使用者,比Outlines更具有操控性靈活性。對於SQL Profiles的category,這裡不做介紹,有興趣的朋友請參考文件。
–The end—
-->>轉載於:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29119536/viewspace-1242420/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- SQL Profiles-Part I--老熊SQL
- 老熊一畝三分地裡的Oracle工具Oracle
- 老熊的三分地-Oracle、UNIX、資料恢復Oracle資料恢復
- 轉至老熊三分地--inside sqlplus prelimIDESQL
- 轉貼老熊_抽絲剝繭分析處理oracle rac crs安裝故障Oracle
- 記一次資料恢復[轉]--學習老熊處理問題的方法資料恢復
- PostgreSQL 從熊燦燦一個獲取固定字元的SQL 分析巧妙之處SQL字元
- 某熊的技術之路指北 ☯
- 熊與猴的轉換(轉)
- 萌熊6月j講題
- 【瞎寫】熊是什麼顏色的?
- 前後端不分離 "老" 專案,SQL 注入漏洞處理實踐後端SQL
- 遊戲防沉迷系統如何智鬥“熊孩子”遊戲
- 熊志男:敏捷測試頭腦風暴敏捷測試
- 老樹常青!SQL為何成為程式設計界的不敗傳奇?SQL程式設計
- css3繪製百度度熊CSSS3
- 夢熊 NOIP 十三連測模擬賽記錄
- 細嗅薔薇的戰熊——俄羅斯遊戲的若干剪影遊戲
- 熊孩子為了玩遊戲有多拼,只有客服知道遊戲
- 黑客組織“奇幻熊”入侵國際田聯絡統黑客
- 普通學渣如何拿到熊廠offer | 掘金技術徵文
- 【位元熊充電棧】Azure OpenAI 特輯,滿電待充OpenAI
- 熊志男:寫給一名測試工程師工程師
- 通達信建倉牛熊爭霸副圖原始碼原始碼
- 【MX-S3】夢熊周賽 · 提高組 3 & FeOI Round 1S3
- 智慧養老導航:開啟便捷養老新篇章
- 智慧養老認證 app:開啟便捷養老新時代APP
- 晚年思考 | 我們需要啥樣的養老 深度老齡化會給養老產業帶來什麼產業
- 寒假“熊孩子大考”將至,小遊戲釋出家長使用指南遊戲
- 【位元熊故事匯】2月MVP英雄故事|有愛的開源MVP
- 多利熊基於分散式架構實踐穩定性建設分散式架構
- 位元熊故事匯2.0|“黑帶”開發人的主場人生
- 熊晨灃藍芽實戰--小程式藍芽連線2.0藍芽
- 老的Websocket介紹Web
- 老的部落格地址
- 智慧養老包含哪些內容?最新智慧養老系統詳解
- 工作效率一路狂飆,年後復工“熊”有妙招
- 【雲和恩墨】內外兼修:Oracle ACED熊軍談Oracle學習Oracle