🎯 学习目标
• ✅ 熟悉慢查询日志结构与核心字段
• ✅ 掌握日志开启与 SQL 记录机制
• ✅ 使用 pt-query-digest 工具进行分析
• ✅ 解读分析结果并提出优化建议
📂 基本概念
项目 内容说明
功能 记录执行时间超过阈值的 SQL
启动参数 slow_query_log=ON, long_query_time=1
默认路径 /var/lib/mysql/xxx-slow.log
适用场景 SQL 优化、性能调优、发现执行瓶颈
简易汇总慢查询模板
mysqldumpslow -s t -t 10 /path/to/slow.log
深度分析工具
pt-query-digest /path/to/slow.log
✅ 第一步:怎么看懂分析报告的结构?
pt-query-digest 的输出可以分为 3 大部分:
1️⃣ 总览 Summary(整个日志的全局统计)
Overall: 2 total, 2 unique, 0.00 QPS
Time range: 2025-04-08T15:28:06 to 2025-04-08T16:35:03
- 2 total:日志中包含 2 次慢查询
- 2 unique:其中每条查询 SQL 都是不同的
- QPS:查询频率(这里非常低,0)
2️⃣ Attribute 分析(汇总每个字段的统计信息)
Attribute total min max avg
Exec time 5s 2s 3s 2s
Rows sent 278.08k 1 278.08k 139.04k
Rows examine 278.08k 1 278.08k 139.04k
字段 | 意义 |
---|---|
Exec time | 查询执行时间(最核心指标) |
Rows sent | 结果中实际返回了多少行(越多越危险) |
Rows examine | 查询过程扫了多少行,是判断是否走索引的重要指标 |
3️⃣ Query Profile(重点来了)
Rank Query ID Response time Calls R/Call V/M
==== =================================== ============= ===== ====== ====
1 0xA373CAF4... 2.9623s 59.7% 1次 2.96s/次 V/M = 0
2 0x59A74D08... 2.0003s 40.3% 1次 2.00s/次 V/M = 0
- Rank:表示排序优先级(执行总时间从高到低)
- Query ID:查询的 hash ID(可忽略)
- Response time:此类 SQL 总共用了多长时间
- Calls:调用次数
- R/Call:每次平均执行时间
- V/M:变异性指数(越大表示执行时间不稳定)
✅ 第二步:如何判断慢 SQL 的“危险程度”?
根据指标分析(索引,字段(内存),where 过滤条件,limit分页)
✅ 第三步:如何定位这类问题场景?
1️⃣ 问自己:“这条 SQL 是否出现在生产代码中?”
-
是测试?没问题
-
是线上代码?⚠️ 高风险!
2️⃣ 用 EXPLAIN 分析执行计划
列名 | 意义 |
---|---|
type | 如果是 ALL,代表全表扫描 ❌ |
key | 如果是 NULL,说明没用索引 ❌ |
rows | 扫描的预计行数,越大越 |
✅ 第四步:怎么优化?
问题类型 | 优化方法 |
---|---|
SELECT * | 替换为只查询所需字段:SELECT id, name |
无 WHERE | 加上过滤条件:WHERE status = ‘active’ |
无索引 | 为 WHERE 使用的字段建立索引 |
没有分页 | 用 LIMIT 控制结果数量 |
🧾 小结:阅读 pt-query-digest 的四步法
步骤 |
---|
1️⃣ 看总览:日志量、执行范围 |
2️⃣ 看 Top Query:哪个 SQL 最慢 |
3️⃣ 看扫行数 vs 返回行数 → 判断是否走索引 |
4️⃣ 用 EXPLAIN 再配合分析是否优化过 |
扩展
场景 | 推荐配置 |
---|---|
日常监控慢 SQL | 开启 slow_query_log=ON,long_query_time=10 |
优化阶段,想抓尽可能多的问题 | 将 long_query_time=0.1,并设 log_queries_not_using_indexes=ON |
生产环境长期使用 | slow_query_log=ON,long_query_time=1,其余视场景设 |
默认 10s
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
生效时间
使用 set global slow_query_log=on; 设置值(重启后就失效了) 写入 配置文件可以解决
🔧 常用排序参数(-s后的值)
mysqldumpslow -s t -t 10 /path/to/slow.log
参数 | 排序依据 | 场景适用 |
---|---|---|
t | 总执行时间 | 哪些 SQL 总耗时最长 |
l | 锁等待时间 | 哪些 SQL 锁住资源时间最长 |
r | 执行次数 | 哪些 SQL 执行得最多 |
c | 返回行数 | 哪些 SQL 导致了最多数据返回 |
al | 平均锁等待时间 | 哪些 SQL 平均锁得最久 |
at | 平均执行时间 | 哪些 SQL 单次平均执行最耗时 |