← 返回首页

数据库索引为什么没有生效

给慢查询加了索引之后,它为什么还是慢吞吞的。

新年的第一个慢查询,比假期后的我还不愿意动。

同事已经给条件字段加了索引,查询时间却几乎没变化。大家围着那条语句看了一会儿,又提出“再加一个索引”。这句话听起来很熟悉,也很危险,于是我先把执行计划拉了出来。

优化器有自己的算盘

查询大致是这样:

EXPLAIN ANALYZE
SELECT id, created_at
FROM orders
WHERE user_id = 1001
ORDER BY created_at DESC
LIMIT 20;

执行计划显示,单列索引只帮忙筛了 user_id,后面仍要处理一大批数据再排序。把索引调整为 user_idcreated_at 的组合后,过滤和排序终于走到了一条路上。

另一次索引失效则更隐蔽:参数是字符串,字段却是数字,隐式类型转换让计划和预想完全不同。还有人习惯给索引列套函数,或者写前置模糊匹配。这些写法看着顺手,索引却常常插不上话。

不是越多越好

我以前也有“慢了就加索引”的阶段。后来表写入变慢,迁移时间越来越长,才发现不少索引彼此重叠,有些几个月都没被用过。

现在遇到慢查询,我先看实际扫描行数、排序开销和预估偏差。统计信息过期、数据分布不均,也会让优化器算错账。只有确认访问路径后,才决定改语句还是改索引。

索引像书后的目录。目录太少,找东西费劲;每一页都做一份目录,书也会厚得拿不动。真正合适的数量,还是要看大家最常翻哪几页。