日期:2014-05-16  浏览次数:20501 次

对索引的一点理解

以前在网上看到一些观点,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进行了变换,把子查询的字段和主查询的字段进行了关联