test1和test2的字段id1都有index,t.opd和s.crd也有index,但以下查询语句就是不走index,请问大家是什么原因?
SELECT t.*,
FROM test1 t,
test2  s
WHERE t.id1 = s.id1
AND t.opd IS NOT NULL
AND s.crd IS NOT NULL
AND t.no_change_opd IS NULL
AND t.opd <= s.crd

解决方案 »

  1.   

    IS NOT NULL,IS NULL 不会走索引。看看你返回的结果集,是否非常庞大。
    并不是走索引的执行计划就是最好的执行计划。你可以通过hint强迫走id1索引,看看效果如何。
      

  2.   

        null值比较特殊,因为null是一个随机的指针,所以null <> null,这就导致索引中不会保存索引值为null的记录(因为index中除了保存索引值之外,还要保存该条记录所在的rowid,既然两个null不相等,也就是说table中存储的null和index中存储的null不是一个值,所以我们无法通过null定位到记录所在的rowid)。
        由于上面描述的原因,oracle不会因为你在谓词条件中给出了t.opd is not null之类的条件就走对应列上的索引,因为所有索引中的内容都符合opd is not null。oracle认为,如果走索引的话,其执行效率反而更差,因为需要对index执行全扫描之后再回表,可以想象大部分数据都满足条件。
      

  3.   

        当然,你也可以按照一楼所说的使用hint强制走索引,但这样做估计也没有太大的帮助,因为索引所以高效在于其强大的过滤性。由于你这个sql中事实上几乎没有过滤掉什么内容,所以走全表扫描反而更好一些。
      

  4.   

    去掉
    AND t.opd IS NOT NULL
    AND s.crd IS NOT NULL
    这两个条件,
    因为只要有一个为空t.opd <= s.crd就是false
      

  5.   

    null不会记录到索引中,当然和null值的比较不会用上索引
    另外可以列出执行计划和表的数据量情况