知用网
白蓝主题五 · 清爽阅读
首页  > 电脑技巧

索引失效导致查询慢?可能是这些原因在作怪

你有没有遇到过这种情况:数据库里明明建了索引,查数据却还是慢得像蜗牛爬?尤其在系统高峰期,页面加载半天出不来,用户抱怨连连。别急着怀疑硬件,问题很可能出在“索引失效”上。

索引不是万能药,用错了照样白搭

很多人以为只要给字段加了索引,查询就一定快。其实不然。比如你在 user 表的 name 字段上建了索引,但写查询语句时这样写:

SELECT * FROM user WHERE SUBSTRING(name, 1, 3) = '张三';

看起来是在查名字,但用了函数包裹字段,数据库引擎没法直接利用索引,只能全表扫描。这就像你有本按拼音排序的电话簿,结果别人非要你找“姓氏笔画数为3的人”,那你还得一页页翻。

隐式类型转换也会让索引失效

假设 user_id 是整型主键,你写了个查询:

SELECT * FROM user WHERE user_id = '123';

看着没问题,但字符串 '123' 和整型 user_id 类型不一致,MySQL 会自动做类型转换。这个转换过程会让索引失效,因为实际执行时变成了 CAST(user_id AS CHAR) = '123',又是字段被函数处理的老问题。

最左前缀原则被忽略

复合索引讲究顺序。比如你给 (city, age, sex) 建了个联合索引,下面这条查询还能用上索引:

SELECT * FROM user WHERE city = '北京' AND age = 25;

但如果写成:

SELECT * FROM user WHERE age = 25 AND sex = '男';

那就用不了索引了。因为没从最左边的 city 开始,数据库不知道该从哪切入。这就像你查字典,必须先知道首字母,才能快速定位。

数据量太少,优化器主动放弃索引

有时候你会发现,同样的 SQL 在测试环境慢,在生产环境反而快。可能原因是测试数据只有几百条,优化器觉得走索引还得回表,不如直接全表扫描来得省事。这不是索引坏了,而是数据库“聪明过头”了。

统计信息过期,执行计划跑偏

MySQL 的查询优化依赖统计信息。如果表数据变了大半,但统计没更新,优化器可能误判索引效率,选了个差的执行计划。可以手动执行 ANALYZE TABLE 来刷新:

ANALYZE TABLE user;

这操作不会锁表太久,但能让执行计划更准确。

别忘了检查索引是否真的存在

有一次同事反馈订单查询特别慢,排查一圈才发现,运维在迁移表的时候忘了重建索引。SHOW INDEX FROM orders 一查,空空如也。所以遇到查询慢,不妨先确认索引还在不在:

SHOW INDEX FROM user;

眼见为实,别想当然。

索引失效的问题,往往藏在细节里。写 SQL 时多留个心眼,查数据前先看执行计划,用 EXPLAIN 分析一下,能少走很多弯路。