性能分析過(guò)程中,經(jīng)常會(huì)遇到生產(chǎn)庫(kù)出現(xiàn)SQL的性能問(wèn)題,但是,我們沒有辦法在生產(chǎn)庫(kù)上做很多動(dòng)作,需要將這個(gè)SQL的對(duì)應(yīng)的表結(jié)構(gòu)信息,統(tǒng)計(jì)信息導(dǎo)入到測(cè)試庫(kù)進(jìn)行測(cè)試(沒有真實(shí)的測(cè)試數(shù)據(jù),只有統(tǒng)計(jì)信息)
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:主機(jī)域名、網(wǎng)絡(luò)空間、營(yíng)銷軟件、網(wǎng)站建設(shè)、蘭山網(wǎng)站維護(hù)、網(wǎng)站推廣。
本次測(cè)試目的,客戶環(huán)境導(dǎo)出了Test和product環(huán)境的相同SQL的不同執(zhí)行計(jì)劃的SQLT報(bào)告。
TEST環(huán)境是11.2.0.1版本
Product是11.2.0.2版本
我們會(huì)將兩個(gè)SQLT報(bào)告分別導(dǎo)入到11.2.0.1和11.2.0.2的測(cè)試環(huán)境中,然后將11.2.0.1版本,好的執(zhí)行計(jì)劃,作為profile導(dǎo)出到11.2.0.2中。讓11.2.0.2也根據(jù)11.2.0.1中的SQL一樣,使用相同的執(zhí)行計(jì)劃。
~~~~~~~第一部分,導(dǎo)入testcase環(huán)境,只導(dǎo)入統(tǒng)計(jì)信息,和表的元數(shù)據(jù)。沒有真實(shí)數(shù)據(jù)~~~~~~
1. 參考sqlt_s39917_readme.html(客戶SQLT輸出的文件中,就已經(jīng)包含這個(gè)readme.html文件)
也可以參考文檔How to Use SQLT (SQLTXPLAIN) to Create a Testcase Without Row Data (Doc ID 1470811.1)
Implement SQLT Test Case (TC) Custom mode Create test case user and schema objects connecting as SYSDBA: sqlplus / as sysdba START sqlt_s39917_metadata.sql Purge pre-existing s39917 from local SQLT repository connected as SYSDBA: START sqlt_s39917_purge.sql Import SQLT repository for s39917 (provide SQLTXPLAIN password): HOS imp sqltxplain FILE=sqlt_s39917_exp.dmp LOG=sqlt_s39917_imp.log TABLES=sqlt% IGNORE=Y Restore CBO schema statistics for test case user connected as SYSDBA: START sqlt_s39917_restore.sql Restore CBO system statistics connected as SYSDBA: START sqlt_s39917_system_stats.sql Set the CBO environment connecting as test case user TC39917 (include optional test case user suffix): CONN TC39917/TC39917 START sqlt_s39917_set_cbo_env.sql Execute test case: START tc.sql
2. 執(zhí)行tc.sql
注意:每次sqlplus連接進(jìn)入后,都需要執(zhí)行最后兩步
CONN TC39917/TC39917 START sqlt_s39917_set_cbo_env.sql Execute test case: START tc.sql ----需要修改q.sql中對(duì)應(yīng)表的用戶名為TC39917
TC.sql執(zhí)行結(jié)果如下
SQL> start tc.sql SQL> REM Executes SQL on TC then produces execution plan. Just execute "@tc.sql" from sqlplus. SQL> SET APPI OFF SERVEROUT OFF; SQL> @@q.sql SQL> SELECT Distinct fc_acc.blnctr_acc, 2 fc_acc.shortcut, 3 fc_acc.acc_name, 4 fc_subject.amount_money_sign, 5 fc_acc.subject_code, 6 fc_acc.corp_code, 7 fc_acc.net_code 8 FROM TC39917.fc_acc, TC39917.fc_user_corp, TC39917.fc_subject 9 WHERE ((fc_acc.corp_code = fc_user_corp.corp_code) OR 10 (acc_cussent is not Null or acc_cussent <> '')) 11 AND (fc_acc.subject_code = fc_subject.subject_code) 12 and ((fc_acc.checker_code is Not Null)) 13 AND (fc_acc.acc_state <> 'R') 14 AND (fc_acc.cur_code = 01) 15 and (fc_acc.acc_state <> 'D') 16 AND (fc_acc.net_code = 1000) 17 AND (fc_acc.acc_type_code = '02' or fc_subject.sys_subject_Code = '1010' or 18 (union_acc is not Null or union_acc <> '')) ; no rows selected SQL> @@plan.sql SQL> REM Displays plan for most recently executed SQL. Just execute "@plan.sql" from sqlplus. SQL> SET PAGES 2000 LIN 180; SQL> SPO plan.log; SQL> --SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR); SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'BASIC ROWS COST PREDICATE')); PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ EXPLAINED SQL STATEMENT: ------------------------ SELECT Distinct fc_acc.blnctr_acc, fc_acc.shortcut, fc_acc.acc_name, fc_subject.amount_money_sign, fc_acc.subject_code, fc_acc.corp_code, fc_acc.net_code FROM fc_acc, fc_user_corp, fc_subject WHERE ((fc_acc.corp_code = fc_user_corp.corp_code) OR (acc_cussent is not Null or acc_cussent <> '')) AND (fc_acc.subject_code = fc_subject.subject_code) and ((fc_acc.checker_code is Not Null)) AND (fc_acc.acc_state <> 'R') AND (fc_acc.cur_code = 01) and (fc_acc.acc_state <> 'D') AND (fc_acc.net_code = 1000) AND (fc_acc.acc_type_code = '02' or fc_subject.sys_subject_Code = '1010' or (union_acc is not Null or union_acc <> '')) Plan hash value: 31035937 ------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Cost (%CPU)| ------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | | 133 (100)| | 1 | HASH UNIQUE | | 4573K| 133 (3)| | 2 | CONCATENATION | | | | | 3 | MERGE JOIN CARTESIAN | | 1 | 42 (0)| | 4 | NESTED LOOPS | | | | | 5 | NESTED LOOPS | | 1 | 36 (0)| |* 6 | TABLE ACCESS FULL | FC_ACC | 1 | 35 (0)| |* 7 | INDEX UNIQUE SCAN | PK_FC_SUBJECT | 1 | 0 (0)| |* 8 | TABLE ACCESS BY INDEX ROWID| FC_SUBJECT | 1 | 1 (0)| | 9 | BUFFER SORT | | 6210 | 41 (0)| | 10 | TABLE ACCESS FULL | FC_USER_CORP | 6210 | 6 (0)| | 11 | MERGE JOIN CARTESIAN | | 1 | 42 (0)| | 12 | NESTED LOOPS | | | | | 13 | NESTED LOOPS | | 1 | 36 (0)| |* 14 | TABLE ACCESS FULL | FC_ACC | 1 | 35 (0)| |* 15 | INDEX UNIQUE SCAN | PK_FC_SUBJECT | 1 | 0 (0)| |* 16 | TABLE ACCESS BY INDEX ROWID| FC_SUBJECT | 1 | 1 (0)| | 17 | BUFFER SORT | | 6210 | 41 (0)| | 18 | TABLE ACCESS FULL | FC_USER_CORP | 6210 | 6 (0)| |* 19 | HASH JOIN | | 122 | 47 (3)| |* 20 | HASH JOIN | | 7 | 41 (3)| |* 21 | TABLE ACCESS FULL | FC_ACC | 8 | 35 (0)| | 22 | TABLE ACCESS FULL | FC_SUBJECT | 636 | 5 (0)| | 23 | TABLE ACCESS FULL | FC_USER_CORP | 6210 | 6 (0)| ------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 6 - filter((TO_NUMBER("FC_ACC"."CUR_CODE")=1 AND "FC_ACC"."ACC_STATE"<>'R' AND "FC_ACC"."ACC_STATE"<>'D' AND "ACC_CUSSENT"<>'' AND "FC_ACC"."CHECKER_CODE" IS NOT NULL AND TO_NUMBER("FC_ACC"."NET_CODE")=1000)) 7 - access("FC_ACC"."SUBJECT_CODE"="FC_SUBJECT"."SUBJECT_CODE") 8 - filter(("FC_ACC"."ACC_TYPE_CODE"='02' OR "FC_SUBJECT"."SYS_SUBJECT_CODE"='1010' OR "UNION_ACC" IS NOT NULL OR "UNION_ACC"<>'')) 14 - filter(("ACC_CUSSENT" IS NOT NULL AND TO_NUMBER("FC_ACC"."CUR_CODE")=1 AND "FC_ACC"."ACC_STATE"<>'R' AND "FC_ACC"."ACC_STATE"<>'D' AND "FC_ACC"."CHECKER_CODE" IS NOT NULL AND TO_NUMBER("FC_ACC"."NET_CODE")=1000 AND LNNVL("ACC_CUSSENT"<>''))) 15 - access("FC_ACC"."SUBJECT_CODE"="FC_SUBJECT"."SUBJECT_CODE") 16 - filter(("FC_ACC"."ACC_TYPE_CODE"='02' OR "FC_SUBJECT"."SYS_SUBJECT_CODE"='1010' OR "UNION_ACC" IS NOT NULL OR "UNION_ACC"<>'')) 19 - access("FC_ACC"."CORP_CODE"="FC_USER_CORP"."CORP_CODE") 20 - access("FC_ACC"."SUBJECT_CODE"="FC_SUBJECT"."SUBJECT_CODE") filter(("FC_ACC"."ACC_TYPE_CODE"='02' OR "FC_SUBJECT"."SYS_SUBJECT_CODE"='1010' OR "UNION_ACC" IS NOT NULL OR "UNION_ACC"<>'')) 21 - filter((TO_NUMBER("FC_ACC"."CUR_CODE")=1 AND "FC_ACC"."ACC_STATE"<>'R' AND "FC_ACC"."ACC_STATE"<>'D' AND "FC_ACC"."CHECKER_CODE" IS NOT NULL AND TO_NUMBER("FC_ACC"."NET_CODE")=1000 AND LNNVL("ACC_CUSSENT" IS NOT NULL) AND LNNVL("ACC_CUSSENT"<>''))) 76 rows selected. SQL> SPO OFF; SQL>
假設(shè),上面的執(zhí)行計(jì)劃是我們期望的,性能優(yōu)異的。我需要導(dǎo)出為profile,并導(dǎo)入到性能較差的數(shù)據(jù)庫(kù)
~~~~~~~~第二部分,導(dǎo)出11.2.0.1的profile~~~~~~~~~~~~~~~~~~~~
3. 生成profile
SQL> @/home/oracle/Bright-temp/sqlt/utl/coe_xfr_sql_profile.sql cwju3syt2mx9a 31035937 SQL> SPO coe_xfr_sql_profile.log; SQL> SET DEF ON TERM OFF ECHO ON FEED OFF VER OFF HEA ON LIN 2000 PAGES 100 LONG 8000000 LONGC 800000 TRIMS ON TI OFF TIMI OFF SERVEROUT ON SIZE 1000000 NUMF "" SQLP SQL>; Parameter 1: SQL_ID (required) PLAN_HASH_VALUE AVG_ET_SECS --------------- ----------- 31035937 .014 Parameter 2: PLAN_HASH_VALUE (required) Values passed to coe_xfr_sql_profile: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SQL_ID : "cwju3syt2mx9a" PLAN_HASH_VALUE: "31035937"
檢查生成的profile執(zhí)行文件,需要修改force_match => TRUE ,并且在新的數(shù)據(jù)庫(kù)執(zhí)行前,還需要針對(duì)新的數(shù)據(jù)庫(kù)的testcase用戶名,修改其中對(duì)應(yīng)的表的用戶名。
vi coe_xfr_sql_profile_cwju3syt2mx9a_31035937.sql
~~~~~~~~第三部分,導(dǎo)入性能差的SQLT到11.2.0.2,并查看執(zhí)行計(jì)劃~~~~~~~~~~~~~~
4. 導(dǎo)入SQLT_product到11.2.0.2上,查看11.2.0.2上這個(gè)SQL的執(zhí)行計(jì)劃
SQL> SPO OFF; SQL> START tc.sql SQL> REM Executes SQL on TC then produces execution plan. Just execute "@tc.sql" from sqlplus. SQL> SET APPI OFF SERVEROUT OFF; SQL> @@q.sql SQL> SELECT Distinct fc_acc.blnctr_acc, 2 fc_acc.shortcut, 3 fc_acc.acc_name, 4 fc_subject.amount_money_sign, 5 fc_acc.subject_code, 6 fc_acc.corp_code, 7 fc_acc.net_code 8 FROM TC34646.fc_acc, TC34646.fc_user_corp, TC34646.fc_subject 9 WHERE ((fc_acc.corp_code = fc_user_corp.corp_code) OR 10 (acc_cussent is not Null or acc_cussent <> '')) 11 AND (fc_acc.subject_code = fc_subject.subject_code) 12 and ((fc_acc.checker_code is Not Null)) 13 AND (fc_acc.acc_state <> 'R') 14 AND (fc_acc.cur_code = 01) 15 and (fc_acc.acc_state <> 'D') 16 AND (fc_acc.net_code = 1000) 17 AND (fc_acc.acc_type_code = '02' or fc_subject.sys_subject_Code = '1010' or 18 (union_acc is not Null or union_acc <> '')); no rows selected SQL> @@plan.sql SQL> REM Displays plan for most recently executed SQL. Just execute "@plan.sql" from sqlplus. SQL> SET PAGES 2000 LIN 180; SQL> SPO plan.log; SQL> --SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR); SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'BASIC ROWS COST PREDICATE')); PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ EXPLAINED SQL STATEMENT: ------------------------ SELECT Distinct fc_acc.blnctr_acc, fc_acc.shortcut, fc_acc.acc_name, fc_subject.amount_money_sign, fc_acc.subject_code, fc_acc.corp_code, fc_acc.net_code FROM TC34646.fc_acc, TC34646.fc_user_corp, TC34646.fc_subject WHERE ((fc_acc.corp_code = fc_user_corp.corp_code) OR (acc_cussent is not Null or acc_cussent <> '')) AND (fc_acc.subject_code = fc_subject.subject_code) and ((fc_acc.checker_code is Not Null)) AND (fc_acc.acc_state <> 'R') AND (fc_acc.cur_code = 01) and (fc_acc.acc_state <> 'D') AND (fc_acc.net_code = 1000) AND (fc_acc.acc_type_code = '02' or fc_subject.sys_subject_Code = '1010' or (union_acc is not Null or union_acc <> '')) Plan hash value: 561502789 -------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| -------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | 278K(100)| | 1 | HASH UNIQUE | | 7469K| 278K (1)| |* 2 | HASH JOIN | | 7469K| 3321 (6)| |* 3 | TABLE ACCESS FULL | FC_ACC | 1156 | 38 (3)| | 4 | MERGE JOIN CARTESIAN| | 4189K| 3197 (3)| | 5 | TABLE ACCESS FULL | FC_SUBJECT | 636 | 5 (0)| | 6 | BUFFER SORT | | 6587 | 3192 (3)| | 7 | TABLE ACCESS FULL | FC_USER_CORP | 6587 | 5 (0)| -------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("FC_ACC"."SUBJECT_CODE"="FC_SUBJECT"."SUBJECT_CODE") filter((("FC_ACC"."CORP_CODE"="FC_USER_CORP"."CORP_CODE" OR "ACC_CUSSENT" IS NOT NULL OR "ACC_CUSSENT"<>'') AND ("FC_ACC"."ACC_TYPE_CODE"='02' OR "FC_SUBJECT"."SYS_SUBJECT_CODE"='1010' OR "UNION_ACC" IS NOT NULL OR "UNION_ACC"<>''))) 3 - filter((TO_NUMBER("FC_ACC"."CUR_CODE")=1 AND "FC_ACC"."ACC_STATE"<>'D' AND "FC_ACC"."CHECKER_CODE" IS NOT NULL AND "FC_ACC"."ACC_STATE"<>'R' AND TO_NUMBER("FC_ACC"."NET_CODE")=1000)) 42 rows selected. SQL> SPO OFF;
5. 在將11.2.0.1的profile導(dǎo)入到11.2.0.2,然后查看profile是否生效
執(zhí)行coe_xfr_sql_profile_cwju3syt2mx9a_31035937.sql前,選需要修改SQL文本為
SELECT Distinct fc_acc.blnctr_acc, fc_acc.shortcut, fc_acc.acc_name, fc_subject.amount_money_sign, fc_acc.subject_code, fc_acc.corp_code, fc_acc.net_code FROM TC34646.fc_acc, <<<<<<<<<<<<<<<<<<<<增加用戶TC34646 TC34646.fc_user_corp, TC34646.fc_subject
6. 執(zhí)行coe腳本
sqlplus / as sysdba SQL>@/home/oracle/Bright-temp/sqlt_s39917_xecute_TEST/coe_xfr_sql_profile_cwju3syt2mx9a_31035937.sql
7. 再次執(zhí)行tc.sql
SQL> CONN TC34646/TC34646 SQL> START sqlt_s34646_set_cbo_env.sql SQL> START tc.sql SQL> REM Executes SQL on TC then produces execution plan. Just execute "@tc.sql" from sqlplus. SQL> SET APPI OFF SERVEROUT OFF; SQL> @@q.sql SQL> SELECT Distinct fc_acc.blnctr_acc, 2 fc_acc.shortcut, 3 fc_acc.acc_name, 4 fc_subject.amount_money_sign, 5 fc_acc.subject_code, 6 fc_acc.corp_code, 7 fc_acc.net_code 8 FROM TC34646.fc_acc, TC34646.fc_user_corp, TC34646.fc_subject 9 WHERE ((fc_acc.corp_code = fc_user_corp.corp_code) OR 10 (acc_cussent is not Null or acc_cussent <> '')) 11 AND (fc_acc.subject_code = fc_subject.subject_code) 12 and ((fc_acc.checker_code is Not Null)) 13 AND (fc_acc.acc_state <> 'R') 14 AND (fc_acc.cur_code = 01) 15 and (fc_acc.acc_state <> 'D') 16 AND (fc_acc.net_code = 1000) 17 AND (fc_acc.acc_type_code = '02' or fc_subject.sys_subject_Code = '1010' or 18 (union_acc is not Null or union_acc <> '')); no rows selected SQL> @@plan.sql SQL> REM Displays plan for most recently executed SQL. Just execute "@plan.sql" from sqlplus. SQL> SET PAGES 2000 LIN 180; SQL> SPO plan.log; SQL> --SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR); SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'BASIC ROWS COST PREDICATE')); PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ EXPLAINED SQL STATEMENT: ------------------------ SELECT Distinct fc_acc.blnctr_acc, fc_acc.shortcut, fc_acc.acc_name, fc_subject.amount_money_sign, fc_acc.subject_code, fc_acc.corp_code, fc_acc.net_code FROM TC34646.fc_acc, TC34646.fc_user_corp, TC34646.fc_subject WHERE ((fc_acc.corp_code = fc_user_corp.corp_code) OR (acc_cussent is not Null or acc_cussent <> '')) AND (fc_acc.subject_code = fc_subject.subject_code) and ((fc_acc.checker_code is Not Null)) AND (fc_acc.acc_state <> 'R') AND (fc_acc.cur_code = 01) and (fc_acc.acc_state <> 'D') AND (fc_acc.net_code = 1000) AND (fc_acc.acc_type_code = '02' or fc_subject.sys_subject_Code = '1010' or (union_acc is not Null or union_acc <> '')) Plan hash value: 31035937 ------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Cost (%CPU)| ------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | | 8755 (100)| | 1 | HASH UNIQUE | | 7469K| 8755 (1)| | 2 | CONCATENATION | | | | | 3 | MERGE JOIN CARTESIAN | | 226K| 245 (3)| | 4 | NESTED LOOPS | | | | | 5 | NESTED LOOPS | | 34 | 73 (2)| |* 6 | TABLE ACCESS FULL | FC_ACC | 35 | 38 (3)| |* 7 | INDEX UNIQUE SCAN | PK_FC_SUBJECT | 1 | 0 (0)| |* 8 | TABLE ACCESS BY INDEX ROWID| FC_SUBJECT | 1 | 1 (0)| | 9 | BUFFER SORT | | 6587 | 244 (3)| | 10 | TABLE ACCESS FULL | FC_USER_CORP | 6587 | 5 (0)| | 11 | MERGE JOIN CARTESIAN | | 2285 | 46 (3)| | 12 | NESTED LOOPS | | | | | 13 | NESTED LOOPS | | 1 | 39 (3)| |* 14 | TABLE ACCESS FULL | FC_ACC | 1 | 38 (3)| |* 15 | INDEX UNIQUE SCAN | PK_FC_SUBJECT | 1 | 0 (0)| |* 16 | TABLE ACCESS BY INDEX ROWID| FC_SUBJECT | 1 | 1 (0)| | 17 | BUFFER SORT | | 6587 | 45 (3)| | 18 | TABLE ACCESS FULL | FC_USER_CORP | 6587 | 7 (0)| |* 19 | HASH JOIN | | 193 | 51 (4)| |* 20 | HASH JOIN | | 11 | 43 (3)| |* 21 | TABLE ACCESS FULL | FC_ACC | 11 | 38 (3)| | 22 | TABLE ACCESS FULL | FC_SUBJECT | 636 | 5 (0)| | 23 | TABLE ACCESS FULL | FC_USER_CORP | 6587 | 7 (0)| ------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 6 - filter((TO_NUMBER("FC_ACC"."CUR_CODE")=1 AND "ACC_CUSSENT"<>'' AND "FC_ACC"."ACC_STATE"<>'D' AND "FC_ACC"."CHECKER_CODE" IS NOT NULL AND "FC_ACC"."ACC_STATE"<>'R' AND TO_NUMBER("FC_ACC"."NET_CODE")=1000)) 7 - access("FC_ACC"."SUBJECT_CODE"="FC_SUBJECT"."SUBJECT_CODE") 8 - filter(("FC_ACC"."ACC_TYPE_CODE"='02' OR "FC_SUBJECT"."SYS_SUBJECT_CODE"='1010' OR "UNION_ACC" IS NOT NULL OR "UNION_ACC"<>'')) 14 - filter(("ACC_CUSSENT" IS NOT NULL AND TO_NUMBER("FC_ACC"."CUR_CODE")=1 AND "FC_ACC"."ACC_STATE"<>'D' AND "FC_ACC"."CHECKER_CODE" IS NOT NULL AND "FC_ACC"."ACC_STATE"<>'R' AND TO_NUMBER("FC_ACC"."NET_CODE")=1000 AND LNNVL("ACC_CUSSENT"<>''))) 15 - access("FC_ACC"."SUBJECT_CODE"="FC_SUBJECT"."SUBJECT_CODE") 16 - filter(("FC_ACC"."ACC_TYPE_CODE"='02' OR "FC_SUBJECT"."SYS_SUBJECT_CODE"='1010' OR "UNION_ACC" IS NOT NULL OR "UNION_ACC"<>'')) 19 - access("FC_ACC"."CORP_CODE"="FC_USER_CORP"."CORP_CODE") 20 - access("FC_ACC"."SUBJECT_CODE"="FC_SUBJECT"."SUBJECT_CODE") filter(("FC_ACC"."ACC_TYPE_CODE"='02' OR "FC_SUBJECT"."SYS_SUBJECT_CODE"='1010' OR "UNION_ACC" IS NOT NULL OR "UNION_ACC"<>'')) 21 - filter((TO_NUMBER("FC_ACC"."CUR_CODE")=1 AND "FC_ACC"."ACC_STATE"<>'D' AND "FC_ACC"."CHECKER_CODE" IS NOT NULL AND "FC_ACC"."ACC_STATE"<>'R' AND TO_NUMBER("FC_ACC"."NET_CODE")=1000 AND LNNVL("ACC_CUSSENT" IS NOT NULL) AND LNNVL("ACC_CUSSENT"<>''))) 74 rows selected. SQL> SPO OFF; SQL>
最終,可以看到,在11.2.0.2上,也按照11.2.0.1上的執(zhí)行計(jì)劃進(jìn)行執(zhí)行SQL了。
這里要強(qiáng)調(diào)一下SQLT真的是非常使用的SQL 調(diào)優(yōu)工具。而且非常易用,很多步驟都在SQLT的HTML文件中,逐步指導(dǎo)。建議大家學(xué)習(xí)使用。
參考文檔:
FAQ: SQLT (SQLTXPLAIN) Frequently Asked Questions (Doc ID 1454160.1)
All About the SQLT Diagnostic Tool (Doc ID 215187.1)
How to Collect Standard Diagnostic Information Using SQLT for SQL Issues (Doc ID 1683772.1)
SQLT Usage Instructions (Doc ID 1614107.1)
How to Generate a SQLT of a SQL Statement That Hangs or Raises an Error (Doc ID 2146816.1)
How to Use SQLT (SQLTXPLAIN) to Create a Testcase Without Row Data (Doc ID 1470811.1)