PLSQL_性能優化系列15_Oracle Explain Plan解析計劃解讀

PLSQL_性能優化系列15_Oracle Explain Plan解析計劃解讀

2014-12-19 Created By BaoXinjian

一、摘要


在SQL語句的執行計劃中,包含很多字段項和很多模塊,其不同字段代表了不同的含義且在不同的情形下某些字段、模塊顯示或不顯示,下

面的描述給出了執行計劃中各字段的含義以及各模塊的描述。

 

二、執行計劃分析過程


1. 分析解析計劃

Step1. 打開熟悉的查看工具:PL/SQL Developer - Toad。

在PL/SQL Developer中寫好一段SQL代碼後,按F5,PL/SQL Developer會自動打開執行計劃窗口,顯示該SQL的執行計劃。

Step2. 查看總COST,獲得資源耗費的總體印象

 一般而言,執行計劃第一行所對應的COST(即成本耗費)值,反應了運行這段SQL的總體估計成本,單看這個總成本沒有實際意義,

但可以拿它與相同邏輯不 同執行計劃的SQL的總體COST進行比較,通常COST低的執行計劃要好一些。  

Step3. 按照從左至右,從上至下的方法,瞭解執行計劃的執行步驟

執行計劃按照層次逐步縮進,從左至右看,縮進最多的那一步,最先執行,如果縮進量相同,則按照從上而下的方法判斷執行順序,可粗略認爲上面的步驟優先執行。

每一個執行步驟都有對應的COST,可從單步COST的高低,以及單步的估計結果集(對應ROWS/基數),來分析表的訪問方式,連接順序以及連接方式是 否合理。

Step4. 分析表的訪問方式

表的訪問方式主要是兩種:

全表掃描(TABLE ACCESS FULL)和索引掃描(INDEX SCAN),如果表上存在選擇性很好的索引,卻走了全表掃描,而且是大表的全表掃描,就說明表的訪問方式可能存在問題;

若大表上沒有合適的索引而走了全表 掃描,就需要分析能否建立索引,或者是否能選擇更合適的表連接方式和連接順序以提高效率。

Step5. 分析表的連接方式和連接順序

表的連接順序:就是以哪張表作爲驅動表來連接其他表的先後訪問順序。

表的連接方式:簡單來講,就是兩個表獲得滿足條件的數據時的連接過程。

主要有三種表連接方式,嵌套循環(NESTED LOOPS)、哈希連接(HASH JOIN)和排序-合併連接(SORT MERGE JOIN)。我們常見得是嵌套循環和哈希連接。

嵌套循環:

最適用也是最簡單的連接方式。類似於用兩層循環處理兩個遊標,外層遊標稱作驅動表,Oracle檢索驅動表的數據,一條一條的代入內層遊標,查找滿足WHERE條件的所有數據,因此內層遊標表中可用索引的選擇性越好,嵌套循環連接的性能就越高。

哈希連接:

先將驅動表的數據按照條件字段以散列的方式放入內存,然後在內存中匹配滿足條件的行。

哈希連接需要有合適的內存,而且必須在CBO優化模式下,連接兩表的WHERE條件有等號的情況下纔可以使用。哈希連接在表的數據量較大,表中沒有合適的索引可用時比嵌套循環的效率要高。

 

2. 總結兩點:

2.1 這裏看到的執行計劃,只是SQL運行前可能的執行方式,實際運行時可能因爲軟硬件環境的不同,而有所改變,而且cost高的執行計劃,不一定在實際運行起來,速度就一定差,我們平時需要結合執行計劃,和實際測試的運行時間,來確定一個執行計劃的好壞。

2.2 對於表的連接順序,多數情況下使用的是嵌套循環,尤其是在索引可用性好的情況下,使用嵌套循環式最好的,但當ORACLE發現需要訪問的數據表較大,索引 的成本較高或者沒有合適的索引可用時,會考慮使用哈希連接,以提高效率。排序合併連接的性能最差,但在存在排序需求,或者存在非等值連接無法使用哈希連接 的情況下,排序合併的效率,也可能比哈希連接或嵌套循環要好。

 

三、執行計劃中各字段的描述


1. 基本字段(總是可用的)

  • Id            執行計劃中每一個操作(行)的標識符。如果數字前面帶有星號,意味着將在隨後提供這行包含的謂詞信息
  • Operation  對應執行的操作。也叫行源操作
  • Name        操作的對象名稱

2. 查詢優化器評估信息

  • Rows(E-Rows)     預估操作返回的記錄條數
  • Bytes(E-Bytes)    預估操作返回的記錄字節數
  • TempSpc            預估操作使用臨時表空間的大小
  • Cost(%CPU)        預估操作所需的開銷。在括號中列出了CPU開銷的百分比。注意這些值是通過執行計劃計算出來的。換句話說,父操作的開銷包含子操作的開銷
  • Time                  預估執行操作所需要的時間(HH:MM:SS)

3. 分區(僅當訪問分區表時下列字段可見)

  • Pstart   訪問的第一個分區。如果解析時不知道是哪個分區就設爲KEY,KEY(I),KEY(MC),KEY(OR),KEY(SQ)
  • Pstop    訪問的最後一個分區。如果解析時不知道是哪個分區就設爲KEY,KEY(I),KEY(MC),KEY(OR),KEY(SQ)

4. 並行和分佈式處理(僅當使用並行或分佈式操作時下列字段可見)

  • Inst         在分佈式操作中,指操作使用的數據庫鏈接的名字
  • TQ          在並行操作中,用於從屬線程間通信的表隊列
  • IN-OUT    並行或分佈式操作間的關係
  • PQ Distrib 在並行操作中,生產者爲發送數據給消費者進行的分配

5. 運行時統計(當設定參數statistics_level爲all或使用gather_plan_statistics提示時,下列字段可見)

  • Starts       指定操作執行的次數
  • A-Rows     操作返回的真實記錄數
  • A-Time     操作執行的真實時間(HH:MM:SS.FF)

6. I/O 統計(當設定參數statistics_level爲all或使用gather_plan_statistics提示時,下列字段可見)

  • Buffers     執行期間進行的邏輯讀操作數量
  • Reads      執行期間進行的物理讀操作數量
  • Writes      執行期間進行的物理寫操作數量         

7. 內存使用統計

  • OMem        最優執行所需內存的預估值
  • 1Mem        一次通過(one-pass)執行所需內存的預估值
  • 0/1/M        最優/一次通過/多次通過(multipass)模式操作執行的次數
  • Used-Mem  最後一次執行時操作使用的內存量
  • Used-Tmp  最後一次執行時操作使用的臨時空間大小。這個字段必須擴大1024倍才能和其他衡量內存的字段一致(比如,32k意味着32MB)
  • Max-Tmp   操作使用的最大臨時空間大小。這個字段必須擴大1024倍才能和其他衡量內存的字段一致(比如,32k意味着32MB)

 

四、執行計劃中各模塊的描述與舉例


1. 執行前,系統預估解析計劃,Explain Plan

複製代碼
SQL> explain plan for                                                                                                    
02.  2  select * from emp e,dept d                                                                                          
03.  3  where e.deptno=d.deptno                                                                                             
04.  4  and e.ename='SMITH';                                                                                                
05.                                                                                                                         
06.Explained.                                                                                                               
15.                                                                                                                         
16.SQL> set linesize 180                                                                                                    
17.SQL> set pagesize 0                                                                                                      
18.SQL> select * from table(dbms_xplan.display(null,null,'advanced'));   --使用dbms_xplan.display函數獲得語句的執行計劃     
19.Plan hash value: 351108634                                            --SQL語句的哈希植                                  
20.                                                                                                                         
21.----------------------------------------------------------------------------------------   /*執行計劃部分*/              
22.| Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Time     |                                 
23.----------------------------------------------------------------------------------------                                 
24.|   0 | SELECT STATEMENT             |         |     1 |   117 |     4   (0)| 00:00:01 |                                 
25.|   1 |  NESTED LOOPS                |         |     1 |   117 |     4   (0)| 00:00:01 |                                 
26.|*  2 |   TABLE ACCESS FULL          | EMP     |     1 |    87 |     3   (0)| 00:00:01 |                                 
27.|   3 |   TABLE ACCESS BY INDEX ROWID| DEPT    |     1 |    30 |     1   (0)| 00:00:01 |                                 
28.|*  4 |    INDEX UNIQUE SCAN         | PK_DEPT |     1 |       |     0   (0)| 00:00:01 |                                 
29.----------------------------------------------------------------------------------------                                 
30.                                                                                                                         
31.Query Block Name / Object Alias (identified by operation id):  --這部分顯示的爲查詢塊名和對象別名                        
32.-------------------------------------------------------------                                                            
33.                                                                                                                         
34.   1 - SEL$1                    --SEL$爲select 的縮寫,位於塊1,相應的還有DEL$,INS$,UPD$等                                
35.   2 - SEL$1 / E@SEL$1          --E@SEL$1,對應到執行計劃中的操作ID爲2上,即在表E上的查詢,E爲別名,下面類同             
36.   3 - SEL$1 / D@SEL$1                                                                                                   
37.   4 - SEL$1 / D@SEL$1                                                                                                   
38.                                                                                                                         
39.Outline Data                    --提綱部分,這部分將執行計劃中的圖形化方式以文本形式來呈現,即轉換爲提示符方式           
40.-------------                                                                                                            
41.                                                                                                                         
42.  /*+                                                                                                                    
43.      BEGIN_OUTLINE_DATA                                                                                                 
44.      USE_NL(@"SEL$1" "D"@"SEL$1")                           --使用USE_NL提示,即嵌套循環                                
45.      LEADING(@"SEL$1" "E"@"SEL$1" "D"@"SEL$1")              --指明前導表                                                
46.      INDEX_RS_ASC(@"SEL$1" "D"@"SEL$1" ("DEPT"."DEPTNO"))   --指明對於D上的訪問方式爲使用索引                           
47.      FULL(@"SEL$1" "E"@"SEL$1")                             --指明對於E上的訪問方式爲全表掃描                           
48.      OUTLINE_LEAF(@"SEL$1")                                                                                             
49.      ALL_ROWS                                                                                                           
50.      OPTIMIZER_FEATURES_ENABLE('10.2.0.3')                                                                              
51.      IGNORE_OPTIM_EMBEDDED_HINTS                                                                                        
52.      END_OUTLINE_DATA                                                                                                   
53.  */                                                                                                                     
54.                                                                                                                         
55.Predicate Information (identified by operation id): --謂詞信息部分,在執行計劃中ID帶有星號的每一行均對應到下面中的一行   
56.---------------------------------------------------                                                                      
57.                                                                                                                         
58.   2 - filter("E"."ENAME"='SMITH')                                                                                       
59.   4 - access("E"."DEPTNO"="D"."DEPTNO")                                                                                 
60.                                                                                                                         
61.Column Projection Information (identified by operation id):  --執行時每一步驟所返回的列,下面的不同步驟返回了不同的列    
62.-----------------------------------------------------------                                                              
63.                                                                                                                         
64.   1 - (#keys=0) "E"."EMPNO"[NUMBER,22], "E"."ENAME"[VARCHAR2,10],                                                       
65.       "E"."JOB"[VARCHAR2,9], "E"."MGR"[NUMBER,22], "E"."HIREDATE"[DATE,7],                                              
66.       "E"."SAL"[NUMBER,22], "E"."COMM"[NUMBER,22], "E"."DEPTNO"[NUMBER,22],                                             
67.       "D"."DEPTNO"[NUMBER,22], "D"."DNAME"[VARCHAR2,14], "D"."LOC"[VARCHAR2,13]                                         
68.   2 - "E"."EMPNO"[NUMBER,22], "E"."ENAME"[VARCHAR2,10], "E"."JOB"[VARCHAR2,9],                                          
69.       "E"."MGR"[NUMBER,22], "E"."HIREDATE"[DATE,7], "E"."SAL"[NUMBER,22],                                               
70.       "E"."COMM"[NUMBER,22], "E"."DEPTNO"[NUMBER,22]                                                                    
71.   3 - "D"."DEPTNO"[NUMBER,22], "D"."DNAME"[VARCHAR2,14], "D"."LOC"[VARCHAR2,13]                                         
72.   4 - "D".ROWID[ROWID,10], "D"."DEPTNO"[NUMBER,22]                                                                      
73.                                                                                                                         
74.Note    --註釋與描述部分,下面的描述中給出了本次SQL語句使用了動態採樣功能                                                
75.-----                                                                                                                    
76.   - dynamic sampling used for this statement                                                                            
77.                                                                                                                         
78.58 rows selected. 

複製代碼

 

2. 執行後,系統實際解析計劃,Explain Plan

複製代碼
SQL> select /*+ gather_plan_statistics */ *          --注意此處增加了提示gather_plan_statistics並且該語句被執行          
02.  2  from emp e,dept d                                                                                                   
03.  3  where e.deptno=d.deptno                                                                                             
04.  4  and e.ename='SMITH';                                                                                                
05.                                                                                                                         
06.      7369 SMITH      CLERK           7902 17-DEC-80        800                    20         20 RESEARCH       DALLAS   
07.                                                                                                                         
08.SQL> select * from table(dbms_xplan.display_cursor(null,null,'iostats last')); --使用display_cursor獲取實際的執行計劃    
09.                                                                                                                         
10.SQL_ID  fpx7zw59f405d, child number 0              --這部分給出了SQL語句的SQL_ID,子游標號以及原始的SQL語句               
11.-------------------------------------                                                                                    
12.select /*+ gather_plan_statistics */ * from emp e,dept d where e.deptno=d.deptno and                                     
13.e.ename='SMITH'                                                                                                          
14.                                                                                                                         
15.Plan hash value: 351108634              --SQL 語句的哈希值                                                               
16.                                        --SQL語句的執行計劃,可以看到下面顯示的字段一部分不同於預估執行計劃中的字段      
17.-----------------------------------------------------------------------------------------------------------              
18.| Id  | Operation                    | Name    | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |              
19.-----------------------------------------------------------------------------------------------------------              
20.|   1 |  NESTED LOOPS                |         |      1 |      1 |      1 |00:00:00.01 |      10 |      1 |              
21.|*  2 |   TABLE ACCESS FULL          | EMP     |      1 |      1 |      1 |00:00:00.01 |       8 |      0 |              
22.|   3 |   TABLE ACCESS BY INDEX ROWID| DEPT    |      1 |      1 |      1 |00:00:00.01 |       2 |      1 |              
23.|*  4 |    INDEX UNIQUE SCAN         | PK_DEPT |      1 |      1 |      1 |00:00:00.01 |       1 |      1 |              
24.-----------------------------------------------------------------------------------------------------------              
25.                                                                                                                         
26.Predicate Information (identified by operation id):                                                                      
27.---------------------------------------------------                                                                      
28.                                                                                                                         
29.   2 - filter("E"."ENAME"='SMITH')                                                                                       
30.   4 - access("E"."DEPTNO"="D"."DEPTNO")                                                                                 
31.                                                                                                                         
32.Note                                                                                                                     
33.-----                                                                                                                    
34.   - dynamic sampling used for this statement                                                                            
35.                                                                                                                         
36.                                                                                                                         
37.26 rows selected.
複製代碼

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章