Skip to content

MySQL 索引优化:先看执行计划再改结构 ​

修订于 2026-10-12:原文“上周遇到”的查询案例、执行时间和“80% 问题靠索引解决”等数字没有可核查记录,已删除。

索引可以帮助 MySQL 更快定位部分查询所需的行,也会占用空间,并增加写入维护成本。优化前要先明确慢在哪里:查询条件、数据分布、回表、排序、关联、锁等待或应用层等待,都可能影响最终响应时间。

一次可复现的诊断流程 ​

  1. 记录 MySQL 版本、SQL、参数、表结构、现有索引和数据量。对敏感数据脱敏。
  2. 用 EXPLAIN 查看优化器计划,关注访问方式、可能使用的索引、实际选择的索引、预估行数、排序和临时表等信息。
  3. 在允许执行该查询的测试环境,用 EXPLAIN ANALYZE 查看实际迭代器时间、返回行数和循环次数。它会执行语句,应先评估查询成本。
  4. 根据 WHERE、JOIN、ORDER BY、GROUP BY 的真实组合设计候选索引。
  5. 在代表性数据上比较更改前后的执行计划、端到端耗时、写入成本和磁盘占用。
  6. 上线前准备回退方案,并监测慢查询与写入延迟。

EXPLAIN 的估计行数不等于实际处理行数;统计信息和数据分布会影响优化器选择。

复合索引的左前缀 ​

MySQL 官方文档说明:复合索引 (a, b, c) 可以用于以 a、(a,b) 或 (a,b,c) 为左前缀的查找;只按 b 或 (b,c) 查找通常不能按这个索引完成同样的定位。实际计划仍由优化器根据条件和统计信息决定。

示例:

sql
CREATE INDEX idx_orders_user_status_created
ON orders (user_id, status, created_at);

这只是说明列顺序的语法,不是对所有订单表的推荐。若主要查询只按 status 过滤,或者选择性、排序方向不同,可能需要另一种设计。不要为了“覆盖所有字段”无限增加索引;索引越多,写入和维护成本也越高。

上线检查 ​

  • 比较典型查询与高写入时段,避免只优化单条 SQL。
  • 确认索引创建对目标版本和表规模的锁、耗时及存储影响。
  • 检查参数分布差异;一个参数快,不代表所有参数都快。
  • 保留原执行计划和指标,若收益不稳定或写入明显恶化,可及时回退。

参考资料 ​

梧桐和风 · 让复杂的技术讲得更清楚