经过几次排除,把问题范围缩小在索引上,首先在确定索引本身没有问题的前提下,考虑索引有没有被使用到,那么新的问题来了,怎么知道指定索引是否被启用。
即将索引至于监控状态下,对索引进行分析。如下对ID_TT_SHOHOU_HIST_002
索引进行分析
字段依次为:
例如常见的,TO_CHAR
、TO_DATE
、TO_NUMBER
、TRUNC
...等等。
此时的解决办法可以使用函数索引,顾名思义就是把使用函数后的字段整体当成索引中的字段。
如下图中的TO_CHAR(SHOHOU_DATE, 'YYYYMMDD')
就是一个函数索引,因为日期字段中含有时分秒,进行日期比较的时候,必须转化成固定的格式。
上面语句中的INDEX_COLUM
字段类型为VARCHAR2
,这时就会发生隐式类型转换,类似于
不等于操作包括:<>
, !=
, NOT colum >= ?
, NOT colum <= ?
替代方式可以使用OR, colum <> 0 =====> colum > 0 or colum < 0;
替代方式:函数索引
通过nvl(b,c)
将为空的字段转为不为空的c值,再在函数nvl(b,c)上建立函数索引
转换前
转换后
组合索引:由多个列构成的索引。如
INDEX_EMP
则为复合索引,COL1
为引导列。进行查询时,可以使用WHERE COL1 = ?
,也可以使用WHERE COL1 = ? AND COL2 = ?
,这样的限制条件都会使用索引,但是WHERE COL2 = ?
,不会使用索引,所以限制条件中包含引导列时,该限制条件才会使用组合索引。
在SELECT
语句后加入/*+INDEX(TTSH ID_TT_SHOHOU_HIST_002)*/
,其中TTSH
是表的别名(当表有别名的时候,必须在索引前加入表的别名)
上面的部分语句因为CALENDER
字段是DATE类型,所以比较时使用了TO_DATE,其实只要把CALENDER
转化成CHAR类型就行了,虽然看起来要改动的地方很多,其实解决了更大的问题。