通過執行計劃看sql的執行路徑

通過執行計劃看sql的執行路徑
今天又有網友問到了有關執行計劃的步驟的問題。通過這個網友給的例子,我就簡單的先講講執行計劃裏我們使用頻率最高,也是最基礎的一項,執行計劃的路徑問題。

這個網友給的是一個最簡單的例子,是sample數據裏的emp和dept的聯合查詢的例子

SQL>select ename,dname from emp,dept where emp.deptno=dept.deptno;

執行計劃
----------------------------------------------------------
Plan hash value: 351108634

----------------------------------------------------------------------------------------
| Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Time    |
----------------------------------------------------------------------------------------
|  0 | SELECT STATEMENT            |        |    14 |  308 |    4  (0)| 00:00:01 |
|  1 |   NESTED LOOPS                |        |    14 |  308 |    4  (0)| 00:00:01 |
|  2 |     TABLE ACCESS FULL          | EMP    |    14 |  126 |    3  (0)| 00:00:01 |
|  3 |     TABLE ACCESS BY INDEX ROWID| DEPT    |    1 |    13 |    1  (0)| 00:00:01 |
|*  4 |      INDEX UNIQUE SCAN        | PK_DEPT |    1 |      |    0  (0)| 00:00:01 |
----------------------------------------------------------------------------------------

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

  4 - access("EMP"."DEPTNO"="DEPT"."DEPTNO")

以上是這個sql的執行計劃,關於上面這個執行計劃是如何出現的,這裏不再贅述。我們直接從如何理解這個sql的執行路徑開始。

通過這個sql和他的執行計劃來看。這條SQL使用CBO的可能性高於RBO的可能性。雖然這裏沒有一個明確的Optimizer=XXXX的提示。主要是根據驅動表的順序來猜測的,當然關於這個Optimizer並不是這裏的主要內容。

那麼根據這個執行計劃的結果,我們如何來理解這個SQL的執行順序叻,其實方法很簡單,就是 同級,從上至下,不同級 從右及左。簡單的口訣如此,

我們一起通過上面的實例來詳細解釋一下。

首先執行計劃結果是一個樹狀結構,其中的一些step存在着父子的關係。最上面的就是root,我們可以把這個樹簡單的描述成

root

    first sub-statement

    second sub-statement

這裏我們所說的同級,從上至下,不同級 從右及左, 表現就是,不同級 從右及左,也就是先執行子句(子句一般較右),子句的結果作爲執行父句的依據。 所以這裏要先執行完子句才用子句的返回來執行父句。 同級,從上至下, 就很好理解了,意味着first sub-statement和second sub-statement同級,那麼先開始上面的,再執行底下的。

現在我們回看到這個sql的執行實例。

  0 | SELECT STATEMENT            |        |    14 |  308 |    4  (0)| 00:00:01 |

這個是root,執行從這裏開始。不過他下面還有

|  1 |   NESTED LOOPS                |        |    14 |  308 |    4  (0)| 00:00:01 |

所以這裏必須先執行完1,才能執行0的。 執行1,我們又可以看到。需要執行

|  2 |     TABLE ACCESS FULL          | EMP    |    14 |  126 |    3  (0)| 00:00:01 |
|  3 |     TABLE ACCESS BY INDEX ROWID| DEPT    |    1 |    13 |    1  (0)| 00:00:01 |

由於2下面已經沒有子句了,所以這裏2可以執行了,2執行完,接着還有3要執行呀。執行到3,我們又發現,3是需要先執行子句

|*  4 |      INDEX UNIQUE SCAN        | PK_DEPT |    1 |      |    0  (0)| 00:00:01 |

這樣先執行了4, 執行完4,4的結果返回給3,作爲3執行的一些輸入。

當3執行完,彙總2,3的執行結果返回執行1. 1執行完,就返回作爲0最後的結果,從而sql執行完畢

所以我們這裏最後可以看到這個sql的執行路徑是 (2)->(4)->(3)->(1)->(0)

既是emp full scan(2) ----> dept index scan(4) ----> 由索引得到rowid ,讀取數據 (3) ----> (1)返回本次查詢結果。嵌套循環,直到得到所有結果。

執行計劃的結果和優化器的模式,數據庫的統計信息都有着比較密切的聯繫。所以相同的sql在不同的數據庫上,甚至有時候是相同的數據,都有可能是不一樣的執行計劃的。

比如,我機器上的這個sql的執行計劃是


---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |     4 |    40 |     7  (15)| 00:00:01 |

|*  1 |  HASH JOIN         |      |     4 |    40 |     7  (15)| 00:00:01 |

|   2 |   TABLE ACCESS FULL| EMP  |     4 |    12 |     3   (0)| 00:00:01 |

|   3 |   TABLE ACCESS FULL| DEPT |     5 |    35 |     3   (0)| 00:00:01 |

---------------------------------------------------------------------------


這裏可以看到和網友的執行計劃,相差很大,其實這裏是基於CBO的,在不同的統計量下這個計劃都會發生變化的。

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/inthirties/archive/2009/06/28/4304864.aspx

發佈了30 篇原創文章 · 獲贊 3 · 訪問量 42萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章