索引失效导致查询慢?可能是这几个坑你踩了

索引不是建了就万事大吉

在日常开发中,很多人觉得只要给数据库字段加上索引,查询速度就能飞起来。但现实往往是:明明加了索引,查数据还是慢得像爬。这时候别急着怀疑硬件,先看看是不是索引压根就没生效——也就是常说的“索引失效”。

比如公司后台有个订单查询功能,按手机号查记录,原本不到1秒返回,最近突然要等5秒以上。排查发现,手机号字段明明有索引,执行计划却显示全表扫描。问题根源,正是索引失效。

常见失效场景一:函数操作让索引作废

最典型的例子是在 WHERE 条件里对字段做函数处理。比如这样写SQL:

SELECT * FROM orders WHERE DATE(create_time) = '2024-03-01';

虽然 create_time 上建了索引,但套了个 DATE() 函数后,数据库无法直接使用索引查找,只能逐行计算,结果就是索引白搭。

正确做法是把函数移到右边,保持字段“干净”:

SELECT * FROM orders WHERE create_time >= '2024-03-01 00:00:00' AND create_time < '2024-03-02 00:00:00';

隐式类型转换也会破坏索引

另一个容易被忽视的问题是字段类型和传入值不匹配。比如手机号字段是 VARCHAR 类型,但查询时用了数字:

SELECT * FROM users WHERE phone = 13812345678;

数据库会自动把字符串字段转成数字比较,相当于在字段上做了类型转换函数,索引自然失效。应该始终用字符串方式查询:

SELECT * FROM users WHERE phone = '13812345678';

联合索引顺序不能乱

三个字段组成的联合索引 (a, b, c),只有按照最左前缀匹配才能生效。如果查询条件只用了 b 和 c,跳过了 a,那这个索引基本用不上。

就像去快递站取件,必须先验手机号(a),再看姓名(b),最后核对取件码(c)。如果你跳过手机号直接报姓名,系统就得挨个翻记录,效率大打折扣。

数据分布影响索引效果

有时候索引没失效,但查询依然慢。比如在一个性别字段上建索引,结果男的占95%,女的5%。当你查“所有女性用户”,数据库可能干脆放弃索引,直接全表扫更快——因为反正要读大量数据页。

这种低基数字段,单独建索引意义不大,反而增加写入负担。

定期检查和优化才是正道

应用迭代多了,SQL 写法五花八门,原来有效的索引可能逐渐被绕开。建议定期用 EXPLAIN 分析慢查询的执行计划,看看是否走了预期索引。

也可以通过监控工具发现全表扫描频繁的表,反向排查 SQL 写法和索引设计。别等到用户投诉“怎么又卡了”,才想起去看数据库。

索引不是一劳永逸的配置,它得跟着业务逻辑一起成长。多留心细节,才能让查询一直跑在快车道上。