862 字
约 2 分钟
7
S11-J04 · 慢查询排查与调优
2024-12-31
2026-11-07

适用读者:线上"突然变慢"要独立定位的人。
前置: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. 自检

  1. 慢日志的四个关键字段各说明什么?
  2. 四步闭环里最容易被跳过的是哪步?
  3. Lock_time 高说明什么?
  4. 深翻的三种优化手段?
  5. 调优优先级为什么把"分库分表"放最后?

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/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。