【新炬網路名師大講堂】執行計劃順序不符合一般規則
在Oracle performance tuning guide中,對執行計劃順序的描述是最右最上最先執行,然後父步驟執行,也就是最右邊的步驟最先執行,如果同等級,那麼最上邊的最先執行,然後執行其父步驟(文件原文: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)。
在實際應用中,這個規則不是完全正確的。ORACLE的SQL內部步驟的執行順序與其計劃中的展現,會有一定的差別,如果不仔細分析,而且一味相信文件,那麼可能會感覺很迷惑。比如在標量子查詢中(scalary subquery),執行計劃的顯示會非常讓人困惑,如:
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;
執行計劃 |
如果按照文件的的分析,顯然ID=2的與ID=1的是同等級的,ID=1的在ID=2的上面,那麼最後執行計劃的順序應該是1—->2—–>0,但是分析下,顯然不是這樣的順序,肯定是必須獲得a.id之後,才能用a.id去查詢B。透過謂詞中的”B”.”ID”=:B1可以看出來,:B1,類似於繫結變數,這裡就2張表,而且根據SQL查詢,肯定來源於A.ID。所以對於標量子查詢的計劃,應該是2—->1—–>0,而且2與1的操作是類似於NESTED LOOPS(與其不同的是,標量子查詢的驅動表是inner table)的操作,每1個A的行,都會執行一次B,當然,ORACLE內部肯定是有最佳化的,這種最佳化就是會快取已經匹配的A.ID值,遇到相同的,不會重複掃描B。可以透過DBMS_XPLAN.DISPLAY_CURSOR詳細看看如何執行的:
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的行驅動訪問B。因為這裡A.ID無重複值,下面插入一行id=1的,因為id=1已經在A表中存在,因此,標量子查詢有快取,所以對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的訪問一次即快取結果,透過A-ROWS可以看到B還是返回2行,而不是3行。所以不要看到標量子查詢就認為效率不行,標量子查詢和FILTER類似,如果能夠對標量子查詢走索引掃描,甚至UNIQUE INDEX SCAN,如果主表查詢的行重複值特別多,效率還是很高的,標量子查詢在一定程度上,消除了JOIN,經常在查詢這種對應某表的行,需要匹配另一表的某個列值,比JOIN效率高(當然,既然類似於NESTED LOOPS了,結果集肯定不會很大,不然效率會差,這個tom的高效設計上有詳細的講解)。
本文主要就是講解下,執行計劃反應了SQL的執行順序,但是如果透過執行計劃準確知道SQL中的執行順序,並不是只要瞭解文件中說的規則就可以了,在實際應用中,可能會碰到這樣那樣的問題,文件當然很少有錯誤,但是文件大多說的都是普遍的規則,SO,在學習過程中,對不理解的問題,要隨時質疑,並論證之。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29960155/viewspace-1373000/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【新炬網路名師大講堂】SOA套件介紹套件
- 【新炬網路名師大講堂】weblogic整合ejbWeb
- 【新炬網路名師大講堂】總結和結論
- 【新炬網路名師大講堂】svn在linux下的使用Linux
- 【新炬網路名師大講堂】關於LOG FILE SYNC的解惑
- 【新炬網路名師大講堂】Oracle Database 12c 新特性總結OracleDatabase
- 【新炬網路名師大講堂】Data Guard–物理主備庫切換
- 【新炬網路名師大講堂】TUXEDO的配置最佳化之路一UX
- 【新炬網路名師大講堂】TUXEDO的配置最佳化之路二UX
- 【新炬網路名師大講堂】初識mysql的體系結構MySql
- 【新炬網路名師大講堂】cursor: pin S wait on X模擬AI
- 【新炬網路名師大講堂】Oracle中的回收站(Recycle Bin)Oracle
- 【新炬網路名師大講堂】clone oracle 12c pluggable databasesOracleDatabase
- 【新炬網路名師大講堂】關於IMSI/MSISDN/IMEI的介紹
- 【新炬網路名師大講堂】12c新特性:備份CDBs和PDBs
- 【新炬網路名師大講堂】12c新特性:使用RMAN連線CDB
- 【新炬網路名師大講堂】AIX上的配置網路調優引數AI
- 【新炬網路名師大講堂】Oracle 11g rac 刪除節點Oracle
- 【新炬網路名師大講堂】j2ee與weblogic簡介Web
- 【新炬網路名師大講堂】oracle application server之核心技術opmnOracleAPPServer
- 【新炬網路名師大講堂】GoldenGate的ADD SCHEMATRANDATA命令研究Go
- 【新炬網路名師大講堂】CBO中”與NULL在cardinality計算上的差別Null
- 【新炬網路名師大講堂】RAC環境下SYSDATE返回錯誤時間
- 【新炬網路名師大講堂】不同資料庫取前幾條記錄資料庫
- 【新炬網路名師大講堂】MySQL複製與監控系列文章(1)——篇首MySql
- 【新炬網路名師大講堂】關於Oracle 12c Flex ASM特性的理解OracleFlexASM
- 【新炬網路名師大講堂】Oracle小知識- Oracle KILLED會話的釋放Oracle會話
- 【新炬網路名師大講堂】WAS控制檯資料來源資訊無故丟失
- 【新炬網路名師大講堂】有限條件下怎樣做好恢復演練
- 【新炬網路名師大講堂】有關DBLINK操作的語句執行機制及最佳化方式
- 【新炬網路名師大講堂】理解TimesTen錯誤日誌資訊”waiting for latch”AI
- 【新炬網路名師大講堂】DATABASE REPLAY加壓播放引數之SCALE_UP_MULTIPLIERDatabase
- 【新炬網路名師大講堂】12c高可用新特性what-if command evaluation介紹
- 【新炬網路名師大講堂】TimesTen記憶體碎片(高水位)回收步驟詳解記憶體
- 【新炬網路名師大講堂】軟體測試中常見問題與解決辦法
- 【新炬網路大師講堂】CMMI/敏捷方法入門敏捷
- 【新炬網路名師大講堂】記一次打PSU遇到的Copy failed的問題AI
- 【新炬網路名師大講堂】讓業務飛起來,應用效能端到端最佳化