在日常的维护中,经常会出现索引失效的情况,什么情况会导致索引失效呢?通过查阅资料总结如下:
一般情况,在大量数据割接完以后,会发生索引实效的情况。
查询dba_indexes表,其索引状态STATUS应该为VALID,如果是DISABLE或者unusable都为不正常索引。
如果是分区索引,可用以下语句进行查询。如下:
selectt.Index_Name,t.Partition_Name,t.Tablespace_Name,t.Status
fromDba_Ind_Partitionst
wheret.Index_Name='INX_SERV_PROD_PRPTY_2'
其中'INX_SERV_PROD_PRPTY_2'是索引名。
执行返回结果如下:
1INX_SERV_PROD_PRPTY_2PARTITION_1RMS_INDXUSABLE
2INX_SERV_PROD_PRPTY_2PARTITION_10RMS_INDXUSABLE
3INX_SERV_PROD_PRPTY_2PARTITION_11RMS_INDXUSABLE
4INX_SERV_PROD_PRPTY_2PARTITION_2RMS_INDXUSABLE
5INX_SERV_PROD_PRPTY_2PARTITION_3RMS_INDXUSABLE
6INX_SERV_PROD_PRPTY_2PARTITION_4RMS_INDXUSABLE
7INX_SERV_PROD_PRPTY_2PARTITION_5RMS_INDXUSABLE
8INX_SERV_PROD_PRPTY_2PARTITION_6RMS_INDXUSABLE
9INX_SERV_PROD_PRPTY_2PARTITION_7RMS_INDXUSABLE
10INX_SERV_PROD_PRPTY_2PARTITION_8RMS_INDXUSABLE
11INX_SERV_PROD_PRPTY_2PARTITION_9RMS_INDXUSABLE
可以查询到每个表分区的索引是否失效。
----
以下原因经常导致索引状态不正常
1)altertablemove
2)alterindexdisable
只有函数索引可以alterindexdisable,一般的应该是alterindexunusable
3)truncate分区表上的全局索引
4)sqlldr(parallelordirect)append导入了重复数据但是索引有唯一约束
5)sqlldrinsert/*+append*/
建议:alterindex索引名rebuildonline;
(B-tree索引:
·索引会随着时间的增加而变的不平衡;
·删除的索引空间不会被重用;
·随着索引层数的增加,索引将会变得无效并需要重建;
·聚簇因子差,索引需要重建;
·为提高性能,索引需要经常重建;
·假如聚簇因子过大,那么重建索引可能会有好处,聚簇因子应该接近块的数量,而非行的数
)
在上线后运行一段时期时候考虑一些大表的索引进行alterindex索引名rebuildonline在线重建
9i以上oracle就建议用DBMS_STATS包来代替ANALYZE语句,如果使用ANALYZE做过分析可能会产生不是很好的分析效果
以下是一般不使用索引的几个常见原因:
1)没有查询条件,或者查询条件没有建立索引
2)在查询条件上没有使用引导列
3)查询的数量是大表的大部分,应该是30%以上。
4)索引本身失效
5)查询条件使用函数在索引列上(见12)
6)对小表查询
7)提示不使用索引
8)统计数据不真实
9)CBO计算走索引花费过大的情况。其实也包含了上面的情况,这里指的是表占有的block要比索引小。
10)隐式转换导致索引失效.这一点应当引起重视.也是开发中经常会犯的错误.
由于表的字段tu_mdn定义为varchar2(20),但在查询时把该字段作为number类型以where条件传给Oracle,这样会导致索引失效.
错误的例子:select*fromtestwheretu_mdn=13333333333;
正确的例子:select*fromtestwheretu_mdn='13333333333';
11)对索引列进行运算导致索引失效,我所指的对索引列进行运算包括(+,-,*,/,!等)
错误的例子:select*fromtestwhereid-1=9;
正确的例子:select*fromtestwhereid=10;
12)使用Oracle内部函数导致索引失效.对于这样情况应当创建基于函数的索引.
错误的例子:select*fromtestwhereround(id)=10;说明,此时id的索引已经不起作用了
正确的例子:首先建立函数索引,createindextest_id_fbi_idxontest(round(id));
然后select*fromtestwhereround(id)=10;这时函数索引起作用了