什么情况下索引会失效?即查询不走索引?

参考回答

索引可能会失效的情况主要发生在查询条件或索引设计不当时,导致数据库无法利用索引来加速查询操作。以下是常见的索引失效场景:
1. 未使用最左前缀原则:对于联合索引,查询条件没有使用索引的最左列。
2. 对索引列进行函数或表达式操作:如 WHERE UPPER(name) = 'ALICE',会导致索引失效。
3. 模糊查询以通配符开头:如 LIKE '%keyword',因为无法定位前缀范围。
4. 不等号操作:如 WHERE age != 30,可能会中断索引使用。
5. 隐式数据类型转换:如字段是字符串类型,但条件是数字类型,会导致索引失效。
6. 查询条件太模糊:如索引选择性低,查询结果覆盖大部分数据行时,数据库可能放弃索引。


详细讲解与拓展

1. 未使用最左前缀原则

联合索引遵循最左前缀匹配原则。如果查询条件未使用索引的最左列,索引将失效。
示例:假设有一个联合索引 (A, B, C)

CREATE INDEX idx_abc ON TableName(A, B, C);
  • 查询 WHERE A = 1 AND B = 2 能使用索引。
  • 查询 WHERE B = 2 AND C = 3 无法使用索引,因为跳过了最左列 A

2. 对索引列使用函数或表达式操作

如果在 WHERE 条件中对索引列使用了函数或表达式,索引无法生效。
示例

SELECT * FROM Users WHERE UPPER(name) = 'ALICE';

解决方法:避免对索引列做函数操作,直接使用原始值比较:

SELECT * FROM Users WHERE name = 'Alice';

3. 模糊查询以通配符开头

当使用 LIKE 查询时,如果通配符 % 在开头,索引无法使用,因为无法确定前缀范围。
示例

SELECT * FROM Products WHERE name LIKE '%phone';  -- 索引失效

解决方法:将 % 放在后面或改用全文索引:

SELECT * FROM Products WHERE name LIKE 'phone%';  -- 索引有效

4. 不等号操作

!=<> 等操作符会导致索引无法完全生效。
示例

SELECT * FROM Users WHERE age != 30;

在这种情况下,数据库无法通过索引快速定位结果,因为需要扫描整个索引范围。

5. 隐式数据类型转换

如果查询条件的值类型与索引列的数据类型不匹配,数据库会进行隐式类型转换,导致索引失效。
示例
假设 phone_number 是字符串类型:

SELECT * FROM Users WHERE phone_number = 12345;  -- 索引失效

解决方法:确保条件类型一致:

SELECT * FROM Users WHERE phone_number = '12345';  -- 索引有效

6. 查询返回大部分数据行(低选择性)

如果查询条件结果覆盖了大部分表的数据行,数据库可能认为全表扫描比使用索引更高效,因此会放弃索引。
示例

SELECT * FROM Users WHERE gender = 'male';  -- gender 索引可能失效

解决方法:结合业务需求,优化索引字段。

7. OR 条件未全部使用索引

如果 OR 条件中有一部分不使用索引,那么整个查询可能放弃索引。
示例

SELECT * FROM Users WHERE name = 'Alice' OR age = 30;  -- age 没有索引,索引失效

解决方法:拆分查询或确保所有字段都有索引:

SELECT * FROM Users WHERE name = 'Alice'
UNION
SELECT * FROM Users WHERE age = 30;

8. ORDER BY 和 GROUP BY 不符合索引顺序

当查询中的排序或分组与索引顺序不匹配时,索引可能失效。
示例

SELECT * FROM Users ORDER BY age DESC;  -- age 有升序索引,倒序可能失效

解决方法:调整查询或索引顺序,使其一致。


总结

索引失效通常与查询条件或索引设计有关。要确保索引生效,应遵循以下原则:
– 对联合索引遵守最左前缀原则。
– 避免对索引列使用函数、表达式或隐式转换。
– 谨慎使用模糊查询、OR 条件和低选择性字段。
通过优化索引设计和查询语句,可以最大化数据库性能。

发表评论

后才能评论