在我2014年總結的「SQL Tuning 基礎概述」中,其實已經介紹了一些查看SQL執行計劃的方法,可是不夠系統和全面,因此本次SQL優化專題,就首先要系統的介紹一下查看SQL執行計劃的方法。
本文示例SQL爲:html
--set lines 1000 pages 1000 select a.empno, a.ename, b.dname, a.job, a.sal from emp a, dept b where a.deptno = b.deptno and empno = 7788;
3.dbms_xplan
3.1 dbms_xplan.display_cursor(null,null,'allstats last')
3.2 dbms_xplan.display_cursor('&sql_id',null,'advanced')
3.3 dbms_xplan.display_awr('&sql_id')sql
reference數據庫
經過explain plan for命令查看SQL的執行計劃,這種方法SQL並不真實執行,通常適用於上線前的SQL預審,尤爲對DML語句,因爲SQL不執行,不用擔憂對生產數據形成影響。這種方法查看的執行計劃有Predicate Information,無Statistics,查看到的執行計劃不必定真實,第三方工具PL/SQL Developer中F5查看執行計劃也是調用的這個方法。
使用explain plan for命令查看SQL的執行計劃:session
explain plan for select a.empno, a.ename, b.dname, a.job, a.sal from emp a, dept b where a.deptno = b.deptno and empno = 7788; select * from table(dbms_xplan.display);
示例以下:運維
JINGYU@jyzhao1 >explain plan for 2 select a.empno, a.ename, b.dname, a.job, a.sal from emp a, dept b where a.deptno = b.deptno and empno = 7788; Explained. Elapsed: 00:00:00.01 JINGYU@jyzhao1 >select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Plan hash value: 1123238657 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 74 | 6 (0)| 00:00:01 | |* 1 | HASH JOIN | | 1 | 74 | 6 (0)| 00:00:01 | |* 2 | TABLE ACCESS FULL| EMP | 1 | 52 | 3 (0)| 00:00:01 | | 3 | TABLE ACCESS FULL| DEPT | 4 | 88 | 3 (0)| 00:00:01 | --------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("A"."DEPTNO"="B"."DEPTNO") 2 - filter("EMPNO"=7788) Note ----- - dynamic sampling used for this statement (level=2) 20 rows selected. Elapsed: 00:00:00.03 JINGYU@jyzhao1 >
經過set autotrace查看SQL的執行計劃,這種方法SQL真實執行(除set autot trace exp針對select語句也不執行,但對DML語句仍是會執行的),這種方法查看的執行計劃有Predicate Information,有Statistics,查看的執行計劃是準確的(注意:若是SQL中包含有綁定變量,那麼用該方法所獲取到的執行計劃,也有可能不是真實的)。但因爲SQL須要真實執行,因此對於有綁定變量值的SQL,還須要輸入對應的變量值才能夠執行,比較麻煩。
使用set autotrace查看SQL的執行計劃:ide
set autotrace on select a.empno, a.ename, b.dname, a.job, a.sal from emp a, dept b where a.deptno = b.deptno and empno = 7788; set autotrace off
示例以下:函數
JINGYU@jyzhao1 >set autotrace on JINGYU@jyzhao1 >select a.empno, a.ename, b.dname, a.job, a.sal from emp a, dept b where a.deptno = b.deptno and empno = 7788; EMPNO ENAME DNAME JOB SAL ---------- ---------- -------------- --------- ---------- 7788 SCOTT RESEARCH ANALYST 3000 Elapsed: 00:00:00.01 Execution Plan ---------------------------------------------------------- Plan hash value: 1123238657 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 74 | 6 (0)| 00:00:01 | |* 1 | HASH JOIN | | 1 | 74 | 6 (0)| 00:00:01 | |* 2 | TABLE ACCESS FULL| EMP | 1 | 52 | 3 (0)| 00:00:01 | | 3 | TABLE ACCESS FULL| DEPT | 4 | 88 | 3 (0)| 00:00:01 | --------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("A"."DEPTNO"="B"."DEPTNO") 2 - filter("EMPNO"=7788) Note ----- - dynamic sampling used for this statement (level=2) Statistics ---------------------------------------------------------- 7 recursive calls 0 db block gets 15 consistent gets 0 physical reads 0 redo size 814 bytes sent via SQL*Net to client 520 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed JINGYU@jyzhao1 >set autotrace off JINGYU@jyzhao1 >
dbms_xplan下面有不少函數能夠調用,其中最經常使用的是display_cursor和display_awr函數,下面依次介紹。
工具
--須要確認statistics_level設置爲ALL,不然SQL語句第一個關鍵字後就須要加上/*+ gather_plan_statistics */,我習慣用前者 show parameter statistics_level(通常數據庫默認是TYPICAL) alter session set statistics_level = ALL; select a.empno, a.ename, b.dname, a.job, a.sal from emp a, dept b where a.deptno = b.deptno and empno = 7788; select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
示例以下:學習
JINGYU@jyzhao1 >alter session set statistics_level = ALL; Session altered. JINGYU@jyzhao1 >select a.empno, a.ename, b.dname, a.job, a.sal from emp a, dept b where a.deptno = b.deptno and empno = 7788; EMPNO ENAME DNAME JOB SAL ---------- ---------- -------------- --------- ---------- 7788 SCOTT RESEARCH ANALYST 3000 JINGYU@jyzhao1 >select * from table(dbms_xplan.display_cursor(null,null,'allstats last')); PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ SQL_ID 39dv3d8jkzyuw, child number 1 ------------------------------------- select a.empno, a.ename, b.dname, a.job, a.sal from emp a, dept b where a.deptno = b.deptno and empno = 7788 Plan hash value: 1123238657 ---------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem | ---------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 7 | | | | |* 1 | HASH JOIN | | 1 | 1 | 1 |00:00:00.01 | 7 | 1214K| 1214K| 762K (0)| |* 2 | TABLE ACCESS FULL| EMP | 1 | 1 | 1 |00:00:00.01 | 3 | | | | | 3 | TABLE ACCESS FULL| DEPT | 1 | 4 | 4 |00:00:00.01 | 4 | | | | ---------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("A"."DEPTNO"="B"."DEPTNO") 2 - filter("EMPNO"=7788) Note ----- - dynamic sampling used for this statement (level=2) 26 rows selected. JINGYU@jyzhao1 >
經過dbms_xplan.display_cursor('&sql_id',null,'advanced')查看SQL的執行計劃,這種方法查看的執行計劃有Predicate Information,無Statistics,SQL是數據庫中以前真實執行過的,對應執行計劃是以前SQL真實執行過的執行計劃,是準確的。使用這種方法的前提是須要SQL的cursor沒有被刷出shared pool,不然查不到結果。
使用dbms_xplan.display_cursor('&sql_id',null,'advanced')查看SQL的執行計劃:測試
--查詢sql_id select sql_id, sql_text from v$sql where sql_text like 'select a.empno%'; 39dv3d8jkzyuw --根據查詢的sql_id查看執行計劃 select * from table(dbms_xplan.display_cursor('&sql_id',null,'advanced')); --附:函數DISPLAY_CURSOR的參數說明 FUNCTION DISPLAY_CURSOR RETURNS DBMS_XPLAN_TYPE_TABLE Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- SQL_ID VARCHAR2 IN DEFAULT CURSOR_CHILD_NO NUMBER(38) IN DEFAULT FORMAT VARCHAR2 IN DEFAULT
示例以下:
JINGYU@jyzhao1 >select * from table(dbms_xplan.display_cursor('&sql_id',null,'advanced')); Enter value for sql_id: 39dv3d8jkzyuw old 1: select * from table(dbms_xplan.display_cursor('&sql_id',null,'advanced')) new 1: select * from table(dbms_xplan.display_cursor('39dv3d8jkzyuw',null,'advanced')) PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ SQL_ID 39dv3d8jkzyuw, child number 0 ------------------------------------- select a.empno, a.ename, b.dname, a.job, a.sal from emp a, dept b where a.deptno = b.deptno and empno = 7788 Plan hash value: 1123238657 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 6 (100)| | |* 1 | HASH JOIN | | 1 | 74 | 6 (0)| 00:00:01 | |* 2 | TABLE ACCESS FULL| EMP | 1 | 52 | 3 (0)| 00:00:01 | | 3 | TABLE ACCESS FULL| DEPT | 4 | 88 | 3 (0)| 00:00:01 | --------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$1 2 - SEL$1 / A@SEL$1 3 - SEL$1 / B@SEL$1 Outline Data ------------- /*+ 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") FULL(@"SEL$1" "A"@"SEL$1") FULL(@"SEL$1" "B"@"SEL$1") LEADING(@"SEL$1" "A"@"SEL$1" "B"@"SEL$1") USE_HASH(@"SEL$1" "B"@"SEL$1") END_OUTLINE_DATA */ Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("A"."DEPTNO"="B"."DEPTNO") 2 - filter("EMPNO"=7788) Column Projection Information (identified by operation id): ----------------------------------------------------------- 1 - (#keys=1) "EMPNO"[NUMBER,22], "A"."ENAME"[VARCHAR2,10], "A"."JOB"[VARCHAR2,9], "A"."SAL"[NUMBER,22], "B"."DNAME"[VARCHAR2,14] 2 - "EMPNO"[NUMBER,22], "A"."ENAME"[VARCHAR2,10], "A"."JOB"[VARCHAR2,9], "A"."SAL"[NUMBER,22], "A"."DEPTNO"[NUMBER,22] 3 - "B"."DEPTNO"[NUMBER,22], "B"."DNAME"[VARCHAR2,14] Note ----- - dynamic sampling used for this statement (level=2) SQL_ID 39dv3d8jkzyuw, child number 1 ------------------------------------- select a.empno, a.ename, b.dname, a.job, a.sal from emp a, dept b where a.deptno = b.deptno and empno = 7788 Plan hash value: 1123238657 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 6 (100)| | |* 1 | HASH JOIN | | 1 | 74 | 6 (0)| 00:00:01 | |* 2 | TABLE ACCESS FULL| EMP | 1 | 52 | 3 (0)| 00:00:01 | | 3 | TABLE ACCESS FULL| DEPT | 4 | 88 | 3 (0)| 00:00:01 | --------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$1 2 - SEL$1 / A@SEL$1 3 - SEL$1 / B@SEL$1 Outline Data ------------- /*+ 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") FULL(@"SEL$1" "A"@"SEL$1") FULL(@"SEL$1" "B"@"SEL$1") LEADING(@"SEL$1" "A"@"SEL$1" "B"@"SEL$1") USE_HASH(@"SEL$1" "B"@"SEL$1") END_OUTLINE_DATA */ Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("A"."DEPTNO"="B"."DEPTNO") 2 - filter("EMPNO"=7788) Column Projection Information (identified by operation id): ----------------------------------------------------------- 1 - (#keys=1) "EMPNO"[NUMBER,22], "A"."ENAME"[VARCHAR2,10], "A"."JOB"[VARCHAR2,9], "A"."SAL"[NUMBER,22], "B"."DNAME"[VARCHAR2,14] 2 - "EMPNO"[NUMBER,22], "A"."ENAME"[VARCHAR2,10], "A"."JOB"[VARCHAR2,9], "A"."SAL"[NUMBER,22], "A"."DEPTNO"[NUMBER,22] 3 - "B"."DEPTNO"[NUMBER,22], "B"."DNAME"[VARCHAR2,14] Note ----- - dynamic sampling used for this statement (level=2) SQL_ID 39dv3d8jkzyuw, child number 2 ------------------------------------- select a.empno, a.ename, b.dname, a.job, a.sal from emp a, dept b where a.deptno = b.deptno and empno = 7788 Plan hash value: 1123238657 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 6 (100)| | |* 1 | HASH JOIN | | 1 | 74 | 6 (0)| 00:00:01 | |* 2 | TABLE ACCESS FULL| EMP | 1 | 52 | 3 (0)| 00:00:01 | | 3 | TABLE ACCESS FULL| DEPT | 4 | 88 | 3 (0)| 00:00:01 | --------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$1 2 - SEL$1 / A@SEL$1 3 - SEL$1 / B@SEL$1 Outline Data ------------- /*+ 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") FULL(@"SEL$1" "A"@"SEL$1") FULL(@"SEL$1" "B"@"SEL$1") LEADING(@"SEL$1" "A"@"SEL$1" "B"@"SEL$1") USE_HASH(@"SEL$1" "B"@"SEL$1") END_OUTLINE_DATA */ Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("A"."DEPTNO"="B"."DEPTNO") 2 - filter("EMPNO"=7788) Column Projection Information (identified by operation id): ----------------------------------------------------------- 1 - (#keys=1) "EMPNO"[NUMBER,22], "A"."ENAME"[VARCHAR2,10], "A"."JOB"[VARCHAR2,9], "A"."SAL"[NUMBER,22], "B"."DNAME"[VARCHAR2,14] 2 - "EMPNO"[NUMBER,22], "A"."ENAME"[VARCHAR2,10], "A"."JOB"[VARCHAR2,9], "A"."SAL"[NUMBER,22], "A"."DEPTNO"[NUMBER,22] 3 - "B"."DEPTNO"[NUMBER,22], "B"."DNAME"[VARCHAR2,14] Note ----- - dynamic sampling used for this statement (level=2) 177 rows selected. JINGYU@jyzhao1 >
因爲上面沒有指定CURSOR_CHILD_NO,因此所有都會顯示出來,固然也能夠指定某個CURSOR_CHILD_NO,好比說:
select * from table(dbms_xplan.display_cursor('&sql_id',0,'advanced'));
這樣結果就只會顯示CURSOR_CHILD_NO=0的執行計劃。
經過dbms_xplan.display_awr('&sql_id')查看SQL的執行計劃,這種方法查看的執行計劃無Predicate Information,無Statistics,查看的執行計劃是準確的。若是對應SQL沒有被抓取到AWR中,就查不到結果。
使用dbms_xplan.display_awr('&sql_id')查看SQL的執行計劃:
--查詢sql_id 39dv3d8jkzyuw --根據查詢的sql_id查看執行計劃 select * from table(dbms_xplan.display_awr('&sql_id')); --附:函數DISPLAY_AWR的參數說明 FUNCTION DISPLAY_AWR RETURNS DBMS_XPLAN_TYPE_TABLE Argument Name Type In/Out Default? ------------------------------ ----------------------- ------ -------- SQL_ID VARCHAR2 IN PLAN_HASH_VALUE NUMBER(38) IN DEFAULT DB_ID NUMBER(38) IN DEFAULT FORMAT VARCHAR2 IN DEFAULT
示例以下:
JINGYU@jyzhao1 >select * from table(dbms_xplan.display_awr('&sql_id')); Enter value for sql_id: 39dv3d8jkzyuw PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------ SQL_ID 39dv3d8jkzyuw -------------------- select a.empno, a.ename, b.dname, a.job, a.sal from emp a, dept b where a.deptno = b.deptno and empno = 7788 Plan hash value: 1123238657 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 6 (100)| | | 1 | HASH JOIN | | 1 | 74 | 6 (0)| 00:00:01 | | 2 | TABLE ACCESS FULL| EMP | 1 | 52 | 3 (0)| 00:00:01 | | 3 | TABLE ACCESS FULL| DEPT | 4 | 88 | 3 (0)| 00:00:01 | --------------------------------------------------------------------------- Note ----- - dynamic sampling used for this statement (level=2) 20 rows selected. JINGYU@jyzhao1 >
也能夠加參數顯示更多的信息,好比能夠顯示出Outline Data,但沒有Predicate Information,沒有Statistics:
JINGYU@jyzhao1 >select * from table(dbms_xplan.display_awr('&sql_id',NULL,NULL,'advanced')); Enter value for sql_id: 39dv3d8jkzyuw PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------ SQL_ID 39dv3d8jkzyuw -------------------- select a.empno, a.ename, b.dname, a.job, a.sal from emp a, dept b where a.deptno = b.deptno and empno = 7788 Plan hash value: 1123238657 --------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 6 (100)| | | 1 | HASH JOIN | | 1 | 74 | 6 (0)| 00:00:01 | | 2 | TABLE ACCESS FULL| EMP | 1 | 52 | 3 (0)| 00:00:01 | | 3 | TABLE ACCESS FULL| DEPT | 4 | 88 | 3 (0)| 00:00:01 | --------------------------------------------------------------------------- Query Block Name / Object Alias (identified by operation id): ------------------------------------------------------------- 1 - SEL$1 2 - SEL$1 / A@SEL$1 3 - SEL$1 / B@SEL$1 Outline Data ------------- /*+ 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") FULL(@"SEL$1" "A"@"SEL$1") FULL(@"SEL$1" "B"@"SEL$1") LEADING(@"SEL$1" "A"@"SEL$1" "B"@"SEL$1") USE_HASH(@"SEL$1" "B"@"SEL$1") END_OUTLINE_DATA */ Note ----- - dynamic sampling used for this statement (level=2) 44 rows selected. JINGYU@jyzhao1 >
經過awrsqrpt查看SQL的執行計劃,這種方式是導出SQL的awr報告,這種方法查看的執行計劃無Predicate Information,但有Statistics,而且同時包含SQL單次和總體的統計信息,查看的執行計劃是準確的。
使用awrsqrpt查看SQL的執行計劃:
@?/rdbms/admin/awrsqrpt
Specify the Begin and End Snapshot Ids ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Enter value for begin_snap: 240 Begin Snapshot Id specified: 240 Enter value for end_snap: 244 End Snapshot Id specified: 244 Specify the SQL Id ~~~~~~~~~~~~~~~~~~ Enter value for sql_id: 39dv3d8jkzyuw SQL ID specified: 39dv3d8jkzyuw ... Report written to awrsqlrpt_1_240_244.html
這種執行計劃的顯示結果以下圖:
經過10046 event的跟蹤文件查看SQL的執行計劃,這種方法查看的執行計劃是準確的,語句中函數,遞歸調用都會被詳細列出,但沒有謂詞信息,並且這種方法獲取執行計劃比較麻煩。
使用10046 event查看SQL的執行計劃:
alter session set events '10046 trace name context forever, level 12'; select a.empno, a.ename, b.dname, a.job, a.sal from emp a, dept b where a.deptno = b.deptno and empno = 7788; alter session set events '10046 trace name context off'; --使用tkprof美化10046 event的跟蹤文件,使其更易讀: tkprof jyzhao1_ora_14139.trc jyzhao1_ora_14139.txt sys=no
示例以下:
JINGYU@jyzhao1 >alter session set events '10046 trace name context forever, level 12'; Session altered. JINGYU@jyzhao1 >select a.empno, a.ename, b.dname, a.job, a.sal from emp a, dept b where a.deptno = b.deptno and empno = 7788; EMPNO ENAME DNAME JOB SAL ---------- ---------- -------------- --------- ---------- 7788 SCOTT RESEARCH ANALYST 3000 JINGYU@jyzhao1 >alter session set events '10046 trace name context off'; Session altered. --使用tkprof美化10046 event的跟蹤文件相關內容以下: SQL ID: 39dv3d8jkzyuw Plan Hash: 1123238657 select a.empno, a.ename, b.dname, a.job, a.sal from emp a, dept b where a.deptno = b.deptno and empno = 7788 call count cpu elapsed disk query current rows ------- ------ -------- ---------- ---------- ---------- ---------- ---------- Parse 1 0.01 0.02 0 8 0 0 Execute 1 0.00 0.00 0 0 0 0 Fetch 2 0.00 0.00 0 7 0 1 ------- ------ -------- ---------- ---------- ---------- ---------- ---------- total 4 0.01 0.02 0 15 0 1 Misses in library cache during parse: 1 Optimizer mode: ALL_ROWS Parsing user id: 91 Number of plan statistics captured: 1 Rows (1st) Rows (avg) Rows (max) Row Source Operation ---------- ---------- ---------- --------------------------------------------------- 1 1 1 HASH JOIN (cr=7 pr=0 pw=0 time=274 us cost=6 size=74 card=1) 1 1 1 TABLE ACCESS FULL EMP (cr=3 pr=0 pw=0 time=67 us cost=3 size=52 card=1) 4 4 4 TABLE ACCESS FULL DEPT (cr=4 pr=0 pw=0 time=15 us cost=3 size=88 card=4) Elapsed times include waiting on following events: Event waited on Times Max. Wait Total Waited ---------------------------------------- Waited ---------- ------------ SQL*Net message to client 2 0.00 0.00 SQL*Net message from client 2 6.55 6.56 ********************************************************************************
關於閱讀這個tkprof美化後文件的方法能夠參考MOS文檔:
關於這個「Oracle之SQL優化專題」的系列,緣起是聽了公司SQL優化專家團隊的分享內容,本身想經過實際操做理解並逐漸測試完善,在我我的以前的職業生涯規劃中一直都偏重於運維方向的DBA,對SQL優化方面瞭解的不多,興趣也不高,是SQL優化專家團隊的此次分享讓我以爲SQL優化也是頗有趣的,因此下決心從今天起單獨開一個專題,本身也能逐漸系統的學習相關知識並記錄下來。初步考慮該系列後續內容同時還會參考崔華的《基於Oracle的SQL優化》一書。最後感謝SQL優化專家團隊的leader勇哥和其團隊全部成員,是大家的此次分享讓我有了作這個專題的動力。