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在这方面还是很智能的,优化器的算法,作为他的核心商业机密,也就不足为奇了。