閑談Oracle執(zhí)行計(jì)劃的步驟順序
經(jīng)過(guò)長(zhǎng)時(shí)間學(xué)習(xí)Oracle,于是和大家分享一下,看完本文你肯定有不少收獲,希望本文能教會(huì)你更多東西。Oracle執(zhí)行計(jì)劃的每一步返回一組行,它們或者為下一步所使用,或者在最后一步時(shí)返回給發(fā)出SQL語(yǔ)句的用戶或應(yīng)用。由每一步返回的一組行叫做行源(row source)。下面得樹狀圖顯示了從一步到另一步行數(shù)據(jù)的流動(dòng)情況。每步的編號(hào)反映了在你觀察Oracle執(zhí)行計(jì)劃時(shí)所示步驟的順序(如何觀察Oracle執(zhí)行計(jì)劃將被簡(jiǎn)短地說(shuō)明)。一般來(lái)說(shuō)這并不是每一步被執(zhí)行的先后順序。

Oracle執(zhí)行計(jì)劃的每一步或者從數(shù)據(jù)庫(kù)中檢索行,或者接收來(lái)自一個(gè)或多個(gè)行源的行數(shù)據(jù)作為輸入:
由紅色字框指出的步驟從數(shù)據(jù)庫(kù)中的數(shù)據(jù)文件中物理檢索數(shù)據(jù)。這種步驟被稱之為存取路徑,后面會(huì)詳細(xì)介紹在Oracle可以使用的存取路徑:
◆第3步和第6步分別的從EMP表和SALGRADE表讀所有的行。
◆第5步在PK_DEPTNO索引中查找由步驟3返回的每個(gè)DEPTNO值。它找出與DEPT表中相關(guān)聯(lián)的那些行的ROWID。
◆第4步從DEPT表中檢索出ROWID為第5步返回的那些行。
由黑色字框指出的步驟在行源上操作,如做2表之間的關(guān)聯(lián),排序,或過(guò)濾等操作,后面也會(huì)給出詳細(xì)的介紹:
◆第2步實(shí)現(xiàn)嵌套的循環(huán)操作(相當(dāng)于C語(yǔ)句中的嵌套循環(huán)),接收從第3步和第4步來(lái)的行源,把來(lái)自第3步源的每一行與它第4步中相應(yīng)的行連接在一起,返回結(jié)果行到第1步。
◆第1步完成一個(gè)過(guò)濾器操作。它接收來(lái)自第2步和第6步的行源,消除掉第2步中來(lái)的,在第6步有相應(yīng)行的那些行,并將來(lái)自第2步的剩下的行返回給發(fā)出語(yǔ)句的用戶或應(yīng)用。
實(shí)現(xiàn)Oracle執(zhí)行計(jì)劃步驟的順序
Oracle執(zhí)行計(jì)劃中的步驟不是按照它們編號(hào)的順序來(lái)實(shí)現(xiàn)的:Oracle首先實(shí)現(xiàn)樹結(jié)構(gòu)圖形里作為葉子出現(xiàn)的那些步驟(例如步驟3、5、6)。由每一步返回的行稱為它下一步驟的行源。然后Oracle實(shí)現(xiàn)父步驟。
舉例來(lái)說(shuō),為了執(zhí)行圖5-1中的語(yǔ)句,Oracle以下列順序?qū)崿F(xiàn)這些步驟:
首先,Oracle實(shí)現(xiàn)步驟3,并一行一行地將結(jié)果行返回給第2步。
對(duì)第3步返回的每一行,Oracle實(shí)現(xiàn)這些步驟:
◆Oracle實(shí)現(xiàn)步驟5,并將結(jié)果ROWID返回給第4步。
◆Oracle實(shí)現(xiàn)步驟4,并將結(jié)果行返回給第2步。
◆Oracle實(shí)現(xiàn)步驟2,將接受來(lái)自第3步的一行和來(lái)自第4步的一行,并返回給第1步一行。
◆Oracle實(shí)現(xiàn)步驟6,如果有結(jié)果行的話,將它返回給第1步。
◆Oracle實(shí)現(xiàn)步驟1,如果從步驟6返回行,Oracle將來(lái)自第2步的行返回給發(fā)出SQL語(yǔ)句的用戶。
注意Oracle對(duì)由第3步返回的每一行實(shí)現(xiàn)步驟5,4,2,6一次。許多父步驟在它們能執(zhí)行之前只需要來(lái)自它們子步驟的單一行。對(duì)這樣的父步驟來(lái)說(shuō),只要從子步驟已返回單一行時(shí)立即實(shí)現(xiàn)父步驟(可能還有Oracle執(zhí)行計(jì)劃的其余部分)。如果該父步驟的父步驟同樣可以通過(guò)單一行返回激活的話,那么它也同樣被執(zhí)行。所以,執(zhí)行可以在樹上串聯(lián)上去,可能包含Oracle執(zhí)行計(jì)劃的余下部分。對(duì)于這樣的操作,可以使用first_rows作為優(yōu)化目標(biāo)以便于實(shí)現(xiàn)快速響應(yīng)用戶的請(qǐng)求。
對(duì)每個(gè)由子步驟依次檢索出來(lái)的每一行,Oracle就實(shí)現(xiàn)父步驟及所有串聯(lián)在一起的步驟一次。對(duì)由子步驟返回的每一行所觸發(fā)的父步驟包括表存取,索引存取,嵌套的循環(huán)連接和過(guò)濾器。
有些父步驟在它們被實(shí)現(xiàn)之前需要來(lái)自子步驟的所有行。對(duì)這樣的父步驟,直到所有行從子步驟返回之前Oracle不能實(shí)現(xiàn)該父步驟。這樣的父步驟包括排序,排序一合并的連接,組功能和總計(jì)。對(duì)于這樣的操作,不能使用first_rows作為優(yōu)化目標(biāo),而可以用all_rows作為優(yōu)化目標(biāo),使該中類型的操作耗費(fèi)的資源最少。
有時(shí)語(yǔ)句執(zhí)行時(shí),并不是象上面說(shuō)的那樣一步一步有先有后的進(jìn)行,而是可能并行運(yùn)行,如在實(shí)際環(huán)境中,3、5、4步可能并行運(yùn)行,以便取得更好的效率。從上面的樹型圖上,是很難看出各個(gè)操作執(zhí)行的先后順序,而通過(guò)Oracle生成的另一種形式的Oracle執(zhí)行計(jì)劃,則可以很容易的看出哪個(gè)操作先執(zhí)行,哪個(gè)后執(zhí)行,這樣的Oracle執(zhí)行計(jì)劃是我們真正需要的,后面會(huì)給出詳細(xì)說(shuō)明?,F(xiàn)在先來(lái)看一些預(yù)備知識(shí)。
【編輯推薦】