根本原因是索引未被使用,而非未建索引;常见失效场景包括where中使用函数、隐式类型转换、like左模糊;应通过explain分析type、key、extra字段,并遵循最左前缀原则合理建索引。

为什么 SELECT 越查越慢,加了索引也没用?
根本原因往往不是没建索引,而是索引没被用上。MySQL 优化器会根据统计信息、条件写法、数据分布等决定是否走索引——WHERE 中用了函数、隐式类型转换、或 LIKE 开头带通配符(如 '%abc'),都会让索引失效。
实操建议:
- 用
EXPLAIN看type字段:如果是ALL或index,基本等于全表扫描 - 检查
key列是否为NULL,是就说明没走索引 - 留意
Extra列:出现Using filesort或Using temporary是性能红灯 - 避免在索引列上做运算,比如
WHERE YEAR(create_time) = 2023→ 改成WHERE create_time >= '2023-01-01' AND create_time
EXPLAIN 输出里哪些字段最关键?
EXPLAIN 不是看有没有“key”就完事,要盯住四个字段:type、key、rows、Extra。
常见误判点:
-
type是range看似还行,但如果rows显示 50 万,说明这个范围太大,实际效率接近全扫 -
key显示用了索引,但Extra写着Using index condition是好事(ICP 下推),而Using where意味着回表后还要过滤,可能意味着索引覆盖不全 -
rows是估算值,不准但有参考性;如果从几千突增到几十万,大概率是统计信息过期,可运行ANALYZE TABLE table_name更新
联合索引怎么建才不白建?
联合索引不是字段堆砌,顺序决定生死。它本质是按最左前缀排序的 B+ 树,只支持“从左到右连续匹配”。
举个例子:索引是 (a, b, c),以下查询能用上:
-
WHERE a = 1 AND b = 2✅(用到前两列) -
WHERE a = 1 AND b > 2 AND c = 3✅(b范围查询后,c无法再走索引,但该条件仍可用于过滤) -
WHERE b = 2 AND c = 3❌(没用a,跳过最左,整个索引失效)
建索引前先看慢查的 WHERE + ORDER BY + SELECT 字段组合,优先把高频过滤字段放左边,排序字段放中间,查询返回字段放右边(用于覆盖索引)。
什么时候该删索引而不是加索引?
索引不是越多越好。每个索引都增加写开销(INSERT/UPDATE/DELETE 都要维护)、占用磁盘、拖慢优化器决策速度。尤其当一个表有 10+ 索引却长期只有 1–2 个被用到,就是信号。
判断依据:
- 查
information_schema.statistics或用sys.schema_unused_indexes(MySQL 8.0+)找长期未命中的索引 - 观察
Handler_read_*状态变量,Handler_read_key很低但Handler_read_next很高,说明索引没起到定位作用 - 单表索引总数超过 5–6 个,且存在字段重复出现在多个索引中(如
(a)、(a,b)、(a,b,c)),优先保留最长的那个
真正难的不是建索引,是识别哪些查询本就不该走索引——比如日志类大表的分页查询 LIMIT 1000000, 20,再好的索引也救不了,得换方案(游标分页、延迟关联、或业务上限制深度)。











