? 在Oracle performance tuning guide中,對執(zhí)行計劃順序的描述是最右最上最先執(zhí)行,然后父步驟執(zhí)行,也就是最右邊的步驟最先執(zhí)行,如果同等級,那么最上邊的最先執(zhí)行,然后執(zhí)行其父步驟(文檔原文:The execution order in EXPLAIN PLAN output begins with
? 在Oracle performance tuning guide中,對執(zhí)行計劃順序的描述是最右最上最先執(zhí)行,然后父步驟執(zhí)行,也就是最右邊的步驟最先執(zhí)行,如果同等級,那么最上邊的最先執(zhí)行,然后執(zhí)行其父步驟(文檔原文:The execution order in EXPLAIN PLAN output begins with the line that is the?furthest indented to the right. The next step is the parent of that line. If two lines?are indented equally, then the top line is normally executed first)。
? ? ? 在實際應(yīng)用中,這個規(guī)則不是完全正確的。ORACLE的SQL內(nèi)部步驟的執(zhí)行順序與其計劃中的展現(xiàn),會有一定的差別,如果不仔細(xì)分析,而且一味相信文檔,那么可能會感覺很迷惑。比如在標(biāo)量子查詢中(scalary subquery),執(zhí)行計劃的顯示會非常讓人困惑,如:
SQL> select * from a; ? ? ? ? ID NAME ———- ———————————- ? ? ? ? ?1 a ? ? ? ? ?2 b ? ? ? ? ?3 c 3 rows selected. SQL> select * from b; SQL> SELECT a.ID,a.NAME,(SELECT b.ID FROM b WHERE a.ID=b.ID)?bid FROM a; 執(zhí)行計劃 |
? ? ??如果按照文檔的的分析,顯然ID=2的與ID=1的是同等級的,ID=1的在ID=2的上面,那么最后執(zhí)行計劃的順序應(yīng)該是1—->2—–>0,但是分析下,顯然不是這樣的順序,肯定是必須獲得a.id之后,才能用a.id去查找B。通過謂詞中的”B”.”ID”=:B1可以看出來,:B1,類似于綁定變量,這里就2張表,而且根據(jù)SQL查詢,肯定來源于A.ID。所以對于標(biāo)量子查詢的計劃,應(yīng)該是2—->1—–>0,而且2與1的操作是類似于NESTED LOOPS(與其不同的是,標(biāo)量子查詢的驅(qū)動表是inner table)的操作,每1個A的行,都會執(zhí)行一次B,當(dāng)然,ORACLE內(nèi)部肯定是有優(yōu)化的,這種優(yōu)化就是會緩存已經(jīng)匹配的A.ID值,遇到相同的,不會重復(fù)掃描B??梢酝ㄟ^DBMS_XPLAN.DISPLAY_CURSOR詳細(xì)看看如何執(zhí)行的:
SQL> @display_cursor SQL_ID ?caq6tcx266xnq, child number 1 ————————————- SELECT a.ID,a.NAME,(SELECT b.ID FROM b WHERE a.ID=b.ID) bid FROM a Plan hash value: 2657529235 Predicate Information (identified by operation id): |
? ? ??其中A共3行,訪問B 3次,返回B 2行,因為有一行不匹配,由A的行驅(qū)動訪問B。因為這里A.ID無重復(fù)值,下面插入一行id=1的,因為id=1已經(jīng)在A表中存在,因此,標(biāo)量子查詢有緩存,所以對B的掃描還是3次,而不是4次,如下:
SQL> INSERT INTO a VALUES(1,’d'); 1 row created. SQL> COMMIT; SQL>??@display_cursor Plan hash value: 2657529235 ———————————————————————————— Predicate Information (identified by operation id): ? ?1 – filter(“B”.”ID”=:B1) |
? ? ?從計劃中可以看到,雖然A是4行,但是因為DISTINCT A.ID是3行,所以還是掃描B 3次,其中ID=1的訪問一次即緩存結(jié)果,通過A-ROWS可以看到B還是返回2行,而不是3行。所以不要看到標(biāo)量子查詢就認(rèn)為效率不行,標(biāo)量子查詢和FILTER類似,如果能夠?qū)?biāo)量子查詢走索引掃描,甚至UNIQUE INDEX SCAN,如果主表查詢的行重復(fù)值特別多,效率還是很高的,標(biāo)量子查詢在一定程度上,消除了JOIN,經(jīng)常在查詢這種對應(yīng)某表的行,需要匹配另一表的某個列值,比JOIN效率高(當(dāng)然,既然類似于NESTED LOOPS了,結(jié)果集肯定不會很大,不然效率會差,這個tom的高效設(shè)計上有詳細(xì)的講解)。
? ?
? ? 本文主要就是講解下,執(zhí)行計劃反應(yīng)了SQL的執(zhí)行順序,但是如果通過執(zhí)行計劃準(zhǔn)確知道SQL中的執(zhí)行順序,并不是只要了解文檔中說的規(guī)則就可以了,在實際應(yīng)用中,可能會碰到這樣那樣的問題,文檔當(dāng)然很少有錯誤,但是文檔大多說的都是普遍的規(guī)則,SO,在學(xué)習(xí)過程中,對不理解的問題,要隨時質(zhì)疑,并論證之。
原文地址:執(zhí)行計劃順序不符合一般規(guī)則, 感謝原作者分享。
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com