返回技术文章

数据库索引为什么没被用上

  • 数据库
  • SQL
  • 性能

示例文章,用于演示分页与列表排版,请替换成你自己的内容。

建了索引却走了全表扫描,是最常见的一类性能问题。原因通常不在索引本身,而在于查询写法让优化器判断「用索引更慢」。

最常见的原因:列上套了函数

-- 索引失效
SELECT * FROM orders WHERE DATE(created_at) = '2026-06-25';

-- 走索引
SELECT * FROM orders
WHERE created_at >= '2026-06-25' AND created_at < '2026-06-26';

第一条在列上套了函数,优化器没法用索引里的有序性去定位范围,只能逐行算。第二条把函数挪到了常量一侧,范围查询可以直接用上索引。

同样的道理适用于隐式类型转换:字符串列拿去和数字比较,等于给列套了一次转换函数。

联合索引的最左前缀

联合索引 (a, b, c) 相当于按 a、再按 b、再按 c 排序。能用的查询必须从最左列开始连续匹配:

查询条件能否用上
a = ?
a = ? AND b = ?
b = ?不能
a = ? AND c = ?只能用到 a

a = ? AND c = ? 这种情况,索引只能把范围缩到 a 相同的那一段,c 的条件要在回表后逐行判断。

选择性太低时优化器会放弃

如果某个条件能匹配表中大部分行,走索引要先扫索引再大量回表,反而比顺序全表扫描更慢。优化器基于统计信息估算代价,判断不划算就不用索引——这是正确的行为。

这时该考虑的不是「怎么逼它用索引」,而是这个查询本身是否需要换一种设计。

怎么确认

不要猜,让数据库告诉你执行计划。各个数据库的命令不同(EXPLAINEXPLAIN ANALYZE 等),关注两件事:实际走了哪个索引,以及估算行数与实际行数差多少。统计信息过期是另一个常见坑。