通過執行計劃看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