天天看點

ORACLE的執行計劃之執行步驟

有了這些背景知識後就開始介紹執行計劃。為了執行語句,Oracle可能必須實作許多步驟。這些步驟中的每一步可能是從資料庫中實體檢索資料行,或者用某種方法準備資料行,供發出語句的使用者使用。Oracle用來執行語句的這些步驟的組合被稱之為執行計劃。執行計劃是SQL優化中最為複雜也是最為關鍵的部分,隻有知道了ORACLE在内部到底是如何執行該SQL語句後,我們才能知道優化器選擇的執行計劃是否為最優的。執行計劃對于DBA來說,就象财務報表對于财務人員一樣重要。是以我們面臨的問題主要是:如何得到執行計劃;如何分析執行計劃,進而找出影響性能的主要問題。下面先從分析樹型執行計劃開始介紹,然後介紹如何得到執行計劃,再介紹如何分析執行計劃。

舉例:

這個例子顯示關于下面SQL語句的執行計劃。

SELECT ename, job, sal, dname

FROM emp, dept

WHERE emp.deptno = derpt.deptno

AND NOT EXISTS

( SELECT *

FROM salgrade

WHERE emp.sal BETWEEN losal AND hisal );

此語句查詢薪水不在任何建議薪水範圍内的所有雇員的名字,工作,薪水和部門名。

下圖5-1顯示了一個執行計劃的圖形表示:

ORACLE的執行計劃之執行步驟

一、執行計劃的步驟

執行計劃的每一步傳回一組行,它們或者為下一步所使用,或者在最後一步時傳回給發出SQL語句的使用者或應用。由每一步傳回的一組行叫做行源(row source)。圖5-1樹狀圖顯示了從一步到另一步行資料的流動情況。每步的編号反映了在你觀察執行計劃時所示步驟的順序(如何觀察執行計劃将被簡短地說明)。一般來說這并不是每一步被執行的先後順序。執行計劃的每一步或者從資料庫中檢索行,或者接收來自一個或多個行源的行資料作為輸入:

由紅色字框指出的步驟從資料庫中的資料檔案中實體檢索資料。這種步驟被稱之為存取路徑,後面會詳細介紹在Oracle可以使用的存取路徑:

第3步和第6步分别的從EMP表和SALGRADE表讀所有的行。

第5步在PK_DEPTNO索引中查找由步驟3傳回的每個DEPTNO值。它找出與DEPT表中相關聯的那些行的ROWID。

第4步從DEPT表中檢索出ROWID為第5步傳回的那些行。

由黑色字框指出的步驟在行源上操作,如做2表之間的關聯,排序,或過濾等操作,後面也會給出詳細的介紹:

第2步實作嵌套的循環操作(相當于C語句中的嵌套循環),接收從第3步和第4步來的行源,把來自第3步源的每一行與它第4步中相應的行連接配接在一起,傳回結果行到第1步。

第1步完成一個過濾器操作。它接收來自第2步和第6步的行源,消除掉第2步中來的,在第6步有相應行的那些行,并将來自第2步的剩下的行傳回給發出語句的使用者或應用。

二、實作執行計劃步驟的順序

執行計劃中的步驟不是按照它們編号的順序來實作的:Oracle首先實作圖5-1樹結構圖形裡作為葉子出現的那些步驟(例如步驟3、5、6)。由每一步傳回的行稱為它下一步驟的行源。然後Oracle實作父步驟。

舉例來說,為了執行圖5-1中的語句,Oracle以下列順序實作這些步驟:

首先,Oracle實作步驟3,并一行一行地将結果行傳回給第2步。

對第3步傳回的每一行,Oracle實作這些步驟:

-- Oracle實作步驟5,并将結果ROWID傳回給第4步。

-- Oracle實作步驟4,并将結果行傳回給第2步。

-- Oracle實作步驟2,将接受來自第3步的一行和來自第4步的一行,并傳回

給第1步一行。

-- Oracle實作步驟6,如果有結果行的話,将它傳回給第1步。

-- Oracle實作步驟1,如果從步驟6傳回行,Oracle将來自第2步的行傳回給

發出SQL語句的使用者。

注意Oracle對由第3步傳回的每一行實作步驟5,4,2,6一次。許多父步驟在它們能執行之前隻需要來自它們子步驟的單一行。對這樣的父步驟來說,隻要從子步驟已傳回單一行時立即實作父步驟(可能還有執行計劃的其餘部分)。如果該父步驟的父步驟同樣可以通過單一行傳回激活的話,那麼它也同樣被執行。是以,執行可以在樹上串聯上去,可能包含執行計劃的餘下部分。對于這樣的操作,可以使用first_rows作為優化目标以便于實作快速響應使用者的請求。

對每個由子步驟依次檢索出來的每一行,Oracle就實作父步驟及所有串聯在一起的步驟一次。對由子步驟傳回的每一行所觸發的父步驟包括表存取,索引存取,嵌套的循環連接配接和過濾器。

有些父步驟在它們被實作之前需要來自子步驟的所有行。對這樣的父步驟,直到所有行從子步驟傳回之前Oracle不能實作該父步驟。這樣的父步驟包括排序,排序一合并的連接配接,組功能和總計。對于這樣的操作,不能使用first_rows作為優化目标,而可以用all_rows作為優化目标,使該中類型的操作耗費的資源最少。