日期:2014-05-16 浏览次数:20524 次
以前在网上看到一些观点,in 或者not in 都不会用到索引,昨天在优化sql的时候,发现这些观点并不对
?
SELECT * FROM WF_DOC_GW_FAWEN F WHERE F.CFBT = 'ee' AND F.NDOCID IN (SELECT DISTINCT GI.SRC_NDOCID FROM WF_DOC_GW_INNER GI, WF_DOC_GW GW WHERE GI.NDOCID = GW.NDOCID AND INSTR(', ' || GW.CPROCUSERLIST || ', ', ', ' || TO_CHAR(45901) || ', ') > 0 AND GI.RETURNSTATUS IS NULL AND GI.SRC_NDOCID IS NOT NULL)
?
?
从上面的执行计划中可以看到WF_DOC_GW_FAWEN的NDOCID字段在执行in的操作中用到了索引,如果子查询的记录数超过一定数量,in的操作也就不会用到索引了。
如果把in或为not in,WF_DOC_GW_FAWEN的NDOCID字段是不会用到索引的,不管子查询的数量是多还是少,但是出现了另外一种情况,WF_DOC_GW_INNER的SRC_NDOCID字段用到了索引,如下
SELECT * FROM WF_DOC_GW_FAWEN F WHERE F.CFBT = 'ee' AND F.NDOCID NOT IN (SELECT DISTINCT GI.SRC_NDOCID FROM WF_DOC_GW_INNER GI, WF_DOC_GW GW WHERE GI.NDOCID = GW.NDOCID AND INSTR(', ' || GW.CPROCUSERLIST || ', ', ', ' || TO_CHAR(45901) || ', ') > 0 AND GI.RETURNSTATUS IS NULL AND GI.SRC_NDOCID IS NOT NULL)
?
由此推断,oracle在解析,编译sql语句的时候,对我们写的sql进行了变换,把子查询的字段和主查询的字段进行了关联