SELECT和DELETE執行計劃的不同選擇
- 2019 年 10 月 27 日
- 筆記
版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/bisal/article/details/102735217
模擬表名,A表的數據量約1000萬,B表的數據量約500萬,進行連接,其中這幾個條件字段,都創建了索引,
SQL> SELECT * from A a inner join B b on a.ID = b.id where b.C_DATE <= trunc(sysdate)-1000;
我們知道在CBO優化器模式下,Oralce會基於Cost成本,來選擇執行計劃。從執行計劃看,全表掃描用的Hash Join,被驅動表只掃描一次,HINT使用索引則用的嵌套循環連接Nested Loop,兩個表的記錄都很多,哪個表做被驅動表都會導致掃描次數過多,回表也過多,而且索引的CF高,索引掃描的成本,會更高些,SELECT返回所有列,需要考慮回表,因此乾脆不回表,選擇全表掃描,從Cost能看出,HINT索引的值更高。
從10053能看到SELECT的執行計劃成本計算,根本沒考慮索引,鑒於SELECT *和較高的CF,能不回表就不回表了,
PLAN_TABLE_OUTPUT ------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------------ | 0 | DELETE STATEMENT | | 10000 | 195K| 5040 (1)| 00:01:01 | | 1 | DELETE | A | | | | | |* 2 | COUNT STOPKEY | | | | | | | 3 | NESTED LOOPS | | 85666 | 1673K| 5040 (1)| 00:01:01 | | 4 | TABLE ACCESS BY INDEX ROWID| B | 85666 | 1171K| 5034 (1)| 00:01:01 | |* 5 | INDEX RANGE SCAN | IDX_B_01 | 85666 | | 232 (1)| 00:00:03 | |* 6 | INDEX UNIQUE SCAN | PK_A_ID | 1 | 6 | 0 (0)| 00:00:01 | ------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter(ROWNUM<=10000) 5 - access("B"."C_DATE"<=TRUNC(SYSDATE@!)-1000) 6 - access("A"."ID"="B"."ID")
DELETE的時候,畢竟要刪除數據,因此回表勢在必行的,只能在回表的各種路徑中找一個合適的,所以會考慮索引路徑,

SELECT和DELETE即使條件相同,相應的執行計劃,可能還是有差別,歸根結底在於Cost的計算和判斷,如上例所示,可能會考慮是否需要回表、CF值高低等因素,所以Oracle在這方面還是很智能的,優化器的算法,作為他的核心商業機密,也就不足為奇了。