862 字
约 2 分钟
7
S11-J04 · 慢查询排查与调优
适用读者:线上"突然变慢"要独立定位的人。
前置:S11-J03。
实测环境:MySQL 8.0.46(慢日志实测,2026-11-05)。
覆盖旧文:847(77) 851(98) 839(85) = 260 点。
覆盖扩展:E-S11-018(慢日志字段解读)。
上一篇:S11-J03 · Explain 逐列读
下一篇:S11-J05 · 日志与恢复。
1. 一句话结论
慢查询排查只有四步:开慢日志 → 找出 Top SQL → EXPLAIN 看计划 → 改写并验证。跳过任何一步都是在猜。
2. 实测:慢日志长什么样
set global slow_query_log=ON;
set global long_query_time=0.05;
set global slow_query_log_file='/tmp/slow.log';
实测输出:
# Query_time: 0.201157 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 1
select sleep(0.2);
| 字段 | 含义 | 用途 |
|---|---|---|
Query_time |
总耗时 | 排序看 Top |
Lock_time |
等锁时间 | 高 → 锁竞争(不是 SQL 慢) |
Rows_sent |
返回行数 | 小 |
Rows_examined |
扫描行数 | 远大于 sent → 索引问题 |
判据:"Rows_examined / Rows_sent 的比值" —— 比值大说明扫了太多无用行。
3. 四步闭环
① 慢日志:找出 Query_time 最长的 N 条(或 Rows_examined 最大的)
② EXPLAIN:看 type / key / rows / Extra
③ 改写:加索引、避免函数、拆大查询、加分页
④ 验证:同样数据量下 Rows_examined 是否下降
第 ④ 步最常被跳过——"改了但没验证"等于没改。
4. 实测:深翻的代价
select id,name from t_user order by id limit 10 offset 10; -- 29 ms
select id,name from t_user order by id limit 10 offset 19990; -- 54 ms
| 观察 | 结论 |
|---|---|
| 2 万行下差约 1.9× | 不是数量级 |
| 百万行会放大 | offset 线性扫描 |
优化手段(按代价从低到高):
| 手段 | 说明 |
|---|---|
| 游标分页 | where id > lastId limit 10 |
| 延迟关联 | 先查主键再 join |
| 限制最大页数 | 产品层兜底 |
5. 调优的优先级
| 优先级 | 手段 | 收益/成本 |
|---|---|---|
| 1 | 加合适索引 | 最高 |
| 2 | 改写 SQL(避免函数/前导模糊/大 IN) |
高 |
| 3 | 分页/限制结果集 | 中 |
| 4 | 缓存 | 中(一致性代价) |
| 5 | 分库分表 | 低(复杂度最高,S08-A01) |
判据:"先做成本最低的那件事了吗?"
6. 五个误区
| 误区 | 真相 |
|---|---|
"慢日志只记 select" |
也记 update/delete |
"Query_time 高一定是 SQL 的问题" |
可能是 Lock_time 高 |
"Rows_sent 小就不慢" |
Rows_examined 可能极大 |
| "改完就好了" | 必须复测 |
| "一开始就分库分表" | 先索引与改写 |
7. 自检
- 慢日志的四个关键字段各说明什么?
- 四步闭环里最容易被跳过的是哪步?
Lock_time高说明什么?- 深翻的三种优化手段?
- 调优优先级为什么把"分库分表"放最后?
8. 下一篇
S11-J05 · 日志与恢复:redo/undo/binlog
排查讲完,下一篇讲"数据怎么不丢、误删怎么救":三种日志的分工与恢复路径。
本篇属于系列《S11 · 数据库与 SQL》。旧文来源:A-847/851/839;扩展点 E-S11-018。慢日志与深翻计时为 MySQL 8.0.46 实测。
S11-J04 · 慢查询排查与调优
https://www.clxhxhhr.top/posts/5334/ 评论
0 条
还没有评论,先写一条吧。