慢查询优化:先看执行计划,再谈加索引
接口变慢,第一反应是加索引。但如果查询本身写得不对(函数包裹字段、隐式转换),加了索引也用不上。
优化的顺序应该是:看执行计划 → 判断扫描行数 → 再决定加索引还是改 SQL。
先说结论
先 EXPLAIN 看 type 与 rows,再加联合索引(区分度高的在前),能用覆盖索引就不回表。
- type 至少要到 range,ALL 是全表扫描
- 联合索引遵守最左前缀
- 把查询字段放进索引可避免回表
- 字段上加函数、隐式类型转换会让索引失效
先把问题说清楚
EXPLAIN 里最该看三列:type(访问方式)、key(用了哪个索引)、rows(预估扫描行数)。
rows 很大而结果很少,说明索引没选对或者区分度太低。
具体怎么做
按顺序执行,每步都验证完再进下一步:
- 用 EXPLAIN 看执行计划,记录 type/key/rows
- 确认 WHERE 条件是否命中索引最左列
- 为多条件查询建联合索引,区分度高的放前面
- 把 SELECT 的列收窄,尽量用覆盖索引
- 用 EXPLAIN ANALYZE(MySQL 8)看真实耗时分布
参数与成本对照
把关键数值摊开,方便判断该选哪条路:
| type | 含义 | 评价 |
|---|---|---|
| const/eq_ref | 主键或唯一索引 | 最好 |
| ref | 非唯一索引匹配 | 好 |
| range | 范围扫描 | 可接受 |
| ALL | 全表扫描 | 需优化 |

几个容易踩的坑
下面这些是最常见的错误做法:
- 给每个字段单独建索引:优化器反而选错
- 在索引列上用函数:WHERE DATE(created_at)=...
- 字符集不一致导致隐式转换:索引失效
- 索引过多影响写入性能
最后补两句
索引是「用写入换读取」。先确认读的性能瓶颈,再决定要不要付这个代价。
工具是手段,理解机制才是能力。命令记不住没关系,知道「该看什么」就够了。
评论 (3)
照着做了一遍,确实少走弯路。第二步最容易漏,建议顺手加个检查清单。
比「一键脚本」有用多了,知道为什么比知道怎么做重要。
补充一句:不同版本行为会变,动手前先确认自己的版本号。
发表评论