Oracle之SQL優化專題01-查看SQL執行計劃的方法

在我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;

1.explain plan for SQL;

經過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 >

2.set autotrace

經過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 >

3.dbms_xplan

dbms_xplan下面有不少函數能夠調用,其中最經常使用的是display_cursor和display_awr函數,下面依次介紹。
工具

3.1 dbms_xplan.display_cursor(null,null,'allstats last')


經過dbms_xplan.display_cursor(null,null,'allstats last')查看SQL的執行計劃,SQL會真實執行(對應的缺點再也不贅述),這種方法查看的執行計劃 有Predicate Information,無Statistics,查看的執行計劃是準確的,而且有每一步真實處理行數和時間
使用dbms_xplan.display_cursor(null,null,'allstats last')查看SQL的執行計劃:

--須要確認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 >

3.2 dbms_xplan.display_cursor('&sql_id',null,'advanced')

經過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的執行計劃。

3.3 dbms_xplan.display_awr('&sql_id')

經過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 >

4.awrsqrpt

經過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

這種執行計劃的顯示結果以下圖:

5.10046 event

經過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文檔:

  • TKProf Interpretation (9i and above) (文檔 ID 760786.1)

reference

關於這個「Oracle之SQL優化專題」的系列,緣起是聽了公司SQL優化專家團隊的分享內容,本身想經過實際操做理解並逐漸測試完善,在我我的以前的職業生涯規劃中一直都偏重於運維方向的DBA,對SQL優化方面瞭解的不多,興趣也不高,是SQL優化專家團隊的此次分享讓我以爲SQL優化也是頗有趣的,因此下決心從今天起單獨開一個專題,本身也能逐漸系統的學習相關知識並記錄下來。初步考慮該系列後續內容同時還會參考崔華的《基於Oracle的SQL優化》一書。最後感謝SQL優化專家團隊的leader勇哥和其團隊全部成員,是大家的此次分享讓我有了作這個專題的動力。

相關文章
相關標籤/搜索