我的sql语句如下:
SELECT ATTID, VALUE FROM REDLINE_MSATTRIBUTE 
WHERE(ATTID, CHANGE_RELEASE_DATE) 
IN (SELECT ATTID, MIN(CHANGE_RELEASE_DATE) FROM REDLINE_MSATTRIBUTE WHERE CLASS = 9000 AND OBJECT_ID = 32718015 
AND CHANGE_RELEASE_DATE >  (SELECT RELEASE_DATE FROM CHANGE WHERE ID = 50839166) 
AND ATTID IN (...此处省略...) GROUP BY ATTID)
AND CLASS = 9000 AND OBJECT_ID = 32718015 AND OLD_VALUE='Y' ORDER BY ATTID, VALUE;给表建了如下的索引:
 CREATE INDEX REDLINE_MSATTRIBUTE_AINDEX ON REDLINE_MSATTRIBUTE
  (
    "ATTID",
    "CHANGE_RELEASE_DATE",
    "CLASS",
    "OBJECT_ID",
    "OLD_VALUE"
  );
但是在执行sql语句的时候,执行计划中并没有使用此索引,有些资料中提到如果索引字段中使用了函数,那么索引不会被使用。那么是不是sql语句中的MIN(CHANGE_RELEASE_DATE)导致改索引不被使用呢?有没有什么办法保证改索引会被使用,或者有什么是发方法替代min函数?
sql 索引 min 函数 执行计划执行计划索引min 函数

解决方案 »

  1.   

    加索引前请重构语句,redline_msattribute这张表一次扫描就可以得出结果了,你的写法多扫描了一次。
      

  2.   

    没用索引的原因,不确定,因为不是很了解你的数据环境。
    另外,min函数的使用,不影响索引的使用。
    如果需要详细讨论,可以和我联系。
    希望二楼的朋友能说下,如何重构?如何一次扫描能完成?
      

  3.   

    问题补充:
    如果把这张表的统计信息删掉,执行的时候就会使用我新建的索引,执行速度会很快;
    如果把表的所有索引全删,执行速度也很快。
    但是目前这2种解决方法都不太可行,因为客户手工收集统计信息后,查询速度依然会很慢;其他索引因为有其他case要用掉,所以不能删除
      

  4.   

    SELECT   attid, VALUE
        FROM (SELECT attid , VALUE, old_value ,
                     RANK () OVER (PARTITION BY attid ORDER BY change_release_date)
                                                                               rn
                FROM redline_msattribute
               WHERE CLASS = 9000
                 AND object_id = 32718015
                 AND change_release_date > (SELECT release_date
                                              FROM CHANGE
                                             WHERE ID = 50839166)
                 AND attid IN (1, 2 , 3))
       WHERE rn = 1 AND old_value = 'Y'
    ORDER BY attid, VALUE;改成这样只扫描一次redline_msattribute表就可以了,至于索引可以考虑在object_id,class,change_release_date,attid上加个组合索引
      

  5.   

    如果表不是太大的话Oracle有可能认为全表扫描比索引更快从而不用索引