核心链路:开启慢查询日志 → 抓到慢 SQL → explain 分析执行计划 → 定位根因 → 优化验证
1.开启慢查询日志
slow_query_log = ON
slow_query_log_file = /xxx/slow.log
long_query_time = 1 # 超过1s记录
log_queries_not_using_indexes = ON # 记录没走索引的SQL
2.抓慢SQL
目的 = 找到那条慢的 SQL 语句(4 种渠道,任选)
1.mysqldumpslow分析慢日志
整理、合并、排序这份日志,
帮你找出最耗时间、执行次数最多的慢 SQL(历史已经跑完的慢 SQL)
👉 适合:查过去一段时间的慢 SQL
2.performance_schema
MySQL 数据库自带的一套监控库
它可以采集 SQL、锁、IO、等待事件
对比慢日志:慢日志只记录超时的 SQL
它还能抓到锁等待、资源等待细节
不能长期开,有性能开销
👉 适合:临时排查,想知道 SQL 是计算慢,还是被锁堵住了
3.业务监控平台
常见有:SkyWalking / Pinpoint / Prometheus+Grafana
Java 后端应用上加埋点的链路工具,不是 MySQL 自带的
一条前端请求过来,经过 controller、service、最后执行 SQL,整条链路都记录下来。
👉 适合:不仅拿到慢 SQL,还能直接看到是哪个接口、哪个业务调用的这条 SQL
(微服务非常好用)
- SkyWalking、Pinpoint:APM 链路追踪工具,从应用端埋点,一条请求链路里直接看到调用了哪条 SQL、耗时多少,不用去数据库捞日志,微服务最常用
- Prometheus+Grafana:指标监控,采集数据库 QPS、RT、慢 SQL 数量、CPU、IO 这些大盘指标,用来告警,定位 "什么时候数据库变慢了"
4.实时抓
相当于给 MySQL 拍一张 "实时快照",看现在这一刻,数据库里面正在跑哪些 SQL
缺点是一闪而过的 SQL 抓不到(一闪而过不代表不是慢SQL,可能你刚要查刚好执行完)
👉 适合:线上现在突然卡了,立刻看有没有 SQL 卡住、锁等待;
show processlist;:SQL 太长会截断show full processlist;:显示完整 SQL 看State字段:可以看到是查询中、锁等待、Sleep 等状态,适合排查现在正在卡住的 SQL
这四个渠道都是用来捞出慢SQL的,只不过使用场景不一样
3.explain
explain 是 MySQL 的执行计划命令,
在 SQL 前面加 explain,MySQL 不会真正执行这条 SQL,而是告诉你:它打算怎么执行这条 SQL

4.定位根因(常见的慢SQL原因)
- 没加索引/索引失效/索引太多,优化器选择了错的索引
- 深分页
- order by /group by 出现 Using filesort / Using temporary
- join 关联慢
- 大事务、锁等待(看起来 SQL 慢,实际不是执行慢)
- 回表太多(二级索引不是覆盖索引)
- 数据量本身巨大,单表扛不住
- 业务层面设计不合理(比如一次性查大量数据、循环里查库...)
慢SQL解决方案
没加索引
补合适联合索引
索引失效
避免索引列运算、隐式转换、左模糊;遵循最左前缀
优化器选错索引
低选择性字段不单独建索引;必要时force index临时修正(慎用)
深分页
见我主页文章
order by/group by 出现 Using filesort / Using temporary
见我主页文章
join 关联慢
拆成多个单表查询
大事务、锁等待(非 SQL 执行慢)
缩短事务生命周期
产分成多批小事务
事务内只保留数据库操作
热点做削峰设计(业务层)
回表太多
建立覆盖索引,查询需要的字段都放进索引
单表数据量过大扛不住
冷热归档
冷热归档:
把冷数据从主表迁移到归档表 / 归档库,主表只留热数据,表变小,索引扫描、查询速度变快
这不也是分库吗
很像:但分库分表是把还在用的数据拆开,冷热混在一起
分库分表
业务不合理
批量查大量
批量查询
循环查库 N+1

