執行計劃的閱讀方法

leon830216發表於2014-03-01
- 第一個列是步驟的ID
- 第二個列是父步驟的ID
- 第三個列是該步驟要進行的操作
- 在執行過程中,父步驟依賴於子步驟。只有對應的所有子步驟執行完,才能執行父步驟
- 先從最開頭一直往右看,直到看到最右邊的並列的地方
- 索引掃描(如:INDEX (UNIQUE SCAN))先忽略掉,只考慮剩下的部分
- 對於不併列的,靠右的先執行(2,3)
- 對於並列的,靠上的先執行(2,4)
- 並列的縮排塊,從上往下執行(2,4)
- 非並列的縮排塊,從下往上執行(2,3)

-- 執行計劃部分
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   NESTED LOOPS
   2    1     TABLE ACCESS (BY INDEX ROWID) OF 'TB_HOST_BATCH_DTL'
   3    2       INDEX (RANGE SCAN) OF 'XIE2TB_HOST_BATCH_DTL' (NON-UNIQUE)
   4    1     TABLE ACCESS (BY INDEX ROWID) OF 'TB_BATCH_TRAN_CTRL'
   5    4       INDEX (UNIQUE SCAN) OF 'SYS_C0034652' (UNIQUE)

不妨假設最右邊的資料為行號,語句執行是按塊進行的
從上述執行計劃的開頭一直往右看,直到找到最右邊並列的,也就是從SELECT STATEMENT開始往右找
找到一級縮排塊,只有一個,沒有優先順序可言,如下
   1    0   NESTED LOOPS
   2    1     TABLE ACCESS (BY INDEX ROWID) OF 'TB_HOST_BATCH_DTL'
   3    2       INDEX (RANGE SCAN) OF 'XIE2TB_HOST_BATCH_DTL' (NON-UNIQUE)
   4    1     TABLE ACCESS (BY INDEX ROWID) OF 'TB_BATCH_TRAN_CTRL'
   5    4       INDEX (UNIQUE SCAN) OF 'SYS_C0034652' (UNIQUE)

再在一級縮排塊中找二級縮排塊,找到兩個,如下
   第一個二級縮排塊:
   2    1     TABLE ACCESS (BY INDEX ROWID) OF 'TB_HOST_BATCH_DTL'
   3    2       INDEX (RANGE SCAN) OF 'XIE2TB_HOST_BATCH_DTL' (NON-UNIQUE)
   第二個二級縮排塊:
   4    1     TABLE ACCESS (BY INDEX ROWID) OF 'TB_BATCH_TRAN_CTRL'
   5    4       INDEX (UNIQUE SCAN) OF 'SYS_C0034652' (UNIQUE)

按照並列塊從上往下執行的原則,第一個二級縮排塊的所有語句將優先於第二個二級縮排塊的語句執行
而兩個二級縮排塊執行完,才能執行一級縮排塊,這是因為非並列的縮排塊,從下往上執行

再在二級縮排塊中找三級縮排塊
第一個二級縮排塊中只有一個三級縮排塊,如下:
   3    2       INDEX (RANGE SCAN) OF 'XIE2TB_HOST_BATCH_DTL' (NON-UNIQUE)
由於沒有更低層級的縮排塊,因此,該塊最先執行。然後執行二級縮排塊

第二個二級縮排塊中也只有一個三級縮排塊,如下
   5    4       INDEX (UNIQUE SCAN) OF 'SYS_C0034652' (UNIQUE)
二級縮排塊中沒有更低層次的縮排塊了,因此,執行完第一個二級縮排塊的所有語句後,便執行此三級縮排塊,再執行對應的二級縮排塊。

兩個二級縮排塊均執行完成後,再執行整個一級縮排塊

因此,若按行排序,語句的執行順序便是: 3 -> 2 -> 5 -> 4 -> 1, 即

   3    2       INDEX (RANGE SCAN) OF 'XIE2TB_HOST_BATCH_DTL' (NON-UNIQUE)
   2    1     TABLE ACCESS (BY INDEX ROWID) OF 'TB_HOST_BATCH_DTL'       
   5    4       INDEX (UNIQUE SCAN) OF 'SYS_C0034652' (UNIQUE)            
   4    1     TABLE ACCESS (BY INDEX ROWID) OF 'TB_BATCH_TRAN_CTRL'       
   1    0   NESTED LOOPS

scott@XE> select * from dept where deptno=10 and dname='ACCOUNTING';

- 星號是指謂詞部分有展開
- access表示這個謂詞條件會改變訪問路徑(表還是索引),是指透過索引可以得到記錄,不必掃描所有資料
- filter表示謂詞條件的值並不會影響資料的訪問路徑,只起到過濾的作用,是指沒透過索引,要將先前的row source掃描一次,根據過濾條件剩下所要的記錄

Execution Plan
----------------------------------------------------------
Plan hash value: 2852011669

---------------------------------------------------------------------------------------
| Id  | Operation                   | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |         |     1 |    20 |     1   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS BY INDEX ROWID| DEPT    |     1 |    20 |     1   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | PK_DEPT |     1 |       |     0   (0)| 00:00:01 |
---------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("DNAME"='ACCOUNTING')
   2 - access("DEPTNO"=10)
   
-- 統計資訊部分
--- db block gets(當前請求的塊數目),當前模式塊意思就是在操作中正好提取的塊數目,而不是在一致性讀的情況下而產生的塊數。正常的情況下,一個查詢提取的塊是在查詢開始的那個時間點上存在的資料塊,當前塊是在這個時刻存在的資料塊,而不是在這個時間點之前或者之後的資料塊數目。
--- consistent gets(資料請求總數在回滾段Buffer中的資料一致性讀所需要的資料塊),這裡的概念是在處理你這個操作的時候需要在一致性讀狀態上處理多少個塊,這些塊產生的主要原因是因為由於在你查詢的過程中,由於其他會話對資料塊進行操 作,而對所要查詢的塊有了修改,但是由於我們的查詢是在這些修改之前呼叫的,所以需要對回滾段中的資料塊的前映像進行查詢,以保證資料的一致性。這樣就產生了一致性讀。
--- physical reads(物理讀),就是從磁碟上讀取資料塊的數量,如果這個值很高,說明要從磁碟請求大量的資料到Buffer Cache裡,通常意味著系統裡存在大量全表掃描的SQL語句,這會影響到資料庫的效能,因此儘量避免語句做全表掃描,對於全表掃描的SQL語句,建議增 加相關的索引,最佳化SQL語句來解決。
--- logic reads(邏輯讀),是指Oracle從記憶體讀到的資料塊數量。logic reads = consistent gets + db block gets。當在記憶體中找不到所需的資料塊的話就需要從磁碟中獲取,於是就產生了 phsical reads。
--- 資料緩衝區的使用命中率 = 1-(physical reads/(db block gets+consistent gets))
--- 檢視資料緩衝區的命中率(查詢出來的結果Buffer Cache的命中率應該在90%以上,否則需要增加資料緩衝區的大小)
    SELECT name,value FROM v$sysstat WHERE name IN ('db block gets','consistent gets','physical reads');

Statistics
----------------------------------------------------------
          0  recursive calls
          2  db block gets
          1  consistent gets
          0  physical reads
          0  redo size
        383  bytes sent via SQL*Net to client
        503  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22558114/viewspace-1097817/,如需轉載,請註明出處,否則將追究法律責任。

相關文章