首页/数据/数据库速查/慢 SQL 定位与优化全流程(场景)
性能与调优57 条

慢 SQL 定位与优化全流程(场景)

真实排障顺序:慢日志/监控发现 → 聚合排序 → EXPLAIN 看计划 → EXPLAIN ANALYZE 验证 → 优化(改写/索引/结构)→ 回归对比 → 纳入巡检。

数据库速查数据更新于 2026-10-13

慢语句定位流程

慢语句定位有一套可复用的顺序:先从慢日志或监控发现候选,再聚合排序挑出性价比最高的目标,接着用执行计划定性、用实测手段确认真实瓶颈,然后优化、回归对比,最后把这条语句纳入巡检。这个顺序的价值在于避免一上来就改最刺眼的那条,而是先看总耗时占比,把时间花在收益最大的地方。

基本信息

起点慢日志、性能视图、监控告警
第二步聚合排序,按总耗时而不是单次耗时挑目标
第三步查看执行计划,判断是索引缺失还是写法问题
第四步实测确认真实行数与耗时分布
第五步优化:改写语句、调整索引或治理表结构
第六步回归对比并纳入巡检

标准步骤

  • 发现:慢日志、性能视图与监控告警提供候选语句
  • 聚合:按总耗时排序,先解决高频或高耗时的少数语句
  • 定性:看执行计划的访问类型、扫描行数与附加信息
  • 实测:用可实际执行的分析手段确认真实瓶颈步骤
  • 优化:改写语句、补或改索引、清理冗余索引、治理表结构
  • 回归:新旧计划与耗时对比,观察一段时间后再收尾

一条龙命令流

一条龙命令流
pt-query-digest --limit 10 /var/log/mysql/slow.log   # 聚合慢日志,按总耗时排出重点
mysql -e "EXPLAIN SELECT ...;"   # 定性:先看执行计划
mysql -e "EXPLAIN ANALYZE SELECT ...;"   # 实测:真实行数与步骤耗时
ALTER TABLE orders ADD INDEX idx_user_created (user_id, created_at);   # 按计划缺口补索引
mysql -e "EXPLAIN ANALYZE SELECT ...;"   # 回归:对比前后差异

各阶段关注点

阶段关注点判断依据
发现慢日志与监控告警确定候选语句集合
聚合总耗时占比先动占比最高的少数几条
定性访问类型与扫描行数区分缺索引与写法问题
实测真实行数与步骤耗时确认瓶颈真正落在哪一步
优化索引与语句改动改动要有明确目标
回归前后计划与耗时对比确认收益且无副作用
巡检纳入周期检查防止计划回退与索引竞争
优化前先立验收线,例如响应时间的分位目标:没有基线的优化等于猜,做完也无法说明是否达标。
优先处理总耗时占比高的语句:单次最慢的那条可能一天只跑一次,而一条中等耗时却每秒上千次的语句才是真正压垮系统的原因。
加了索引之后要回归其他语句:新增索引可能改变优化器选择,让原本正常的查询变慢,这是典型的索引竞争问题。

定位流程检查清单

  • 确认慢日志与监控采样是否覆盖业务高峰
  • 按总耗时排序挑目标,而不是按单次最慢
  • 记录当前耗时与执行计划作为基线
  • 一次只调整一个变量,便于归因
  • 回归观察期覆盖完整业务周期
  • 把优化结论写进知识库,避免同类问题重复排查
有些问题不在索引上:锁等待、连接堆积、磁盘写入能力不足都会让语句变慢,执行计划看着正常的慢语句要往这几个方向继续查,而不是反复改 SQL。
优化完成后留一段观察期:改索引与改语句都可能影响其他业务,观察期内盯住整体耗时分布与错误率,确认没有把问题转移到别处再关闭任务单。

易错点

  • 跳过聚合直接改最刺眼的一条:时间花在低价值目标上,真正的瓶颈依旧存在
  • 优化后不做回归:新增索引让另一条查询变慢时无人发现,问题被搬到别处
  • 只改语句不看索引:条件列缺索引时任何改写都摆脱不了全表扫描
  • 优化没有基线与验收线:无法证明改动有效,也无法判断是否达到业务要求
  • 反复改同一条语句却不看真实执行数据:凭经验猜测瓶颈,改动方向经常是错的

数据来源与参考

  • MySQL 8.0 Reference Manual: Optimization
  • Percona Toolkit: pt-query-digest

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌