oracle: 索引失效的情况
索引失效: 即索引未被使用或无法使用; 索引失效不等于SQL失效
查询条件不匹配索引
比如: 联合索引违反了最左原则
复合索引在列 (A, B)
上,但查询条件中只使用了列 B
数据类型不匹配
查询条件中的数据类型与索引列的数据类型不一致
隐式类型转换
解决:
1.修改查询条件为where id ='123'(优先)
2.将索引列的数据类型从 VARCHAR2
改为适合存储数字的类型,如 NUMBER
。这样可以避免在查询时进行类型转换
在索引列上使用函数或表达式
-
如果需要使用函数,可以考虑创建函数索引
索引列上使用数学计算
数学计算(+ - * /)
解决: 比如 字段+值1=值2 改成 字段=值2-值1
在索引字段中使用了空值判断
is null 和 is not null 属于空值判断
可以给包含NULL值的字段创建索引,但是oracle 不会为 NULL
值创建索引条目,如果查询条件中涉及 NULL
值,索引可能不会被使用
在 WHERE
子句中使用不等连接
如 <>
、!=
、NOT IN
、NOT EXISTS,like
等
这并不是绝对的,具体是否失效取决于查询的具体情况以及优化器的选择
解决: 使用索引提示(Hints)强制让优化器选择索引扫描
语法
示例
优化器模式
不同的优化器模式可能导致优化器选择不同的执行计划
CBO : 基于成本的优化器(Cost-Based Optimizer),CBO会根据统计信息和成本模型来评估不同执行计划的成本,并选择成本最低的计划
查看当前会话或实例的优化器模式
SELECT name, value FROM v$parameter WHERE name = 'optimizer_mode';
SELECT name, value FROM v$system_parameter WHERE name = 'optimizer_mode';
示例
通过执行计划了解使用的优化器
使用 EXPLAIN PLAN
语句为你的 SQL 查询生成执行计划
查询执行计划
返回的执行计划中OPERATION列中显示了优化器选择的访问路径和操作方法
例如,TABLE ACCESS FULL
表示优化器选择了全表扫描,而 INDEX RANGE SCAN
表示优化器选择了索引范围扫描
修改优化器模式
低选择性
如果索引列的选择性很低(即列中有大量重复值),优化器可能会选择全表扫描而不是使用索引,比如索引列是 GENDER
,只有 M
和 F
两个值
并行查询
并行查询可能导致优化器选择全表扫描而不是使用索引
解决:
1.禁止并行查询
2.使用查询提示NO_PARALLEL
3.分析查询计划
使用 EXPLAIN PLAN
,了解优化器为何选择并行查询,并根据需要调整查询或索引
统计信息不准确
表的统计信息过期或不准确,导致优化器错误地选择了全表扫描
索引被标记为不可用
索引碎片过多
索引碎片过多会导致索引性能下降,甚至失效
索引碎片指的是索引结构中由于数据的增删改操作导致索引块(Index Blocks)不再连续存储,或者索引中存在许多小的、不连续的空闲空间
查询索引的碎片化情况
leaf_blocks:这个列表示索引占用的数据块数量。数据块数量越多,可能意味着索引越大
解决
1.重建索引,可以整理索引块,减少碎片化
2.优化数据操作来减少索引碎片的产生, 比如批量插入、更新和删除