pt-query-digest仅支持标准MySQL慢查询日志(含# Time:、# Query_time:等注释头),需配合--group-by fingerprint等参数才能有效分析,关键指标是Response time占比和Time/call。

MySQL 慢查询日志路径和格式必须匹配 pt-query-digest 要求
pt-query-digest 默认只解析标准 MySQL 慢查询日志(slow_query_log = ON 且 log_output = FILE),不支持 general_log、JSON 格式或 MariaDB 的 slow log 变体。如果日志里出现 # Time:、# User@Host:、# Query_time: 这类注释头,基本能用;若全是纯 SQL 或带 SET timestamp= 行但无时间戳注释,则大概率解析失败。
常见问题包括:
- 启用了
log_output = TABLE:必须先用SELECT * INTO OUTFILE导出为文本,再用--filter重写时间戳字段 - 日志被轮转或压缩(如
slow.log.2.gz):pt-query-digest 支持直接读取.gz,但不能读.xz或.zst - MySQL 8.0+ 启用了
log_slow_extra = ON:新增的# Schema:、# Rows_affected:等字段不影响解析,可保留
pt-query-digest 基础分析命令要加关键参数
裸跑 pt-query-digest /var/lib/mysql/slow.log 往往得不到有用结果——默认只输出前 10 条,且不聚合相似语句(比如 WHERE id = 1 和 WHERE id = 2 被当不同查询)。必须加 --group-by fingerprint 才按抽象语法树归类。
推荐最小可用命令:
pt-query-digest --group-by fingerprint --limit 20 /var/lib/mysql/slow.log
其他高频参数作用:
-
--since "2024-06-01 00:00:00":只分析指定时间后的日志,避免全量扫描 -
--filter '$event->{Bytes} > 1024':过滤掉返回数据量小于 1KB 的查询(适合定位大结果集慢查) -
--report-format json:输出 JSON 方便下游程序解析(注意是json不是json-pretty) -
--no-report+--print:只打印原始解析后的标准化 SQL,用于调试指纹是否合理
识别“伪慢查询”:Query_time 不等于执行耗时
MySQL 慢查询日志里的 Query_time 是从语句进入排队队列开始计时,包含锁等待、磁盘 I/O 等待,不是纯 CPU 执行时间。所以你会看到:
- 一条
SELECT * FROM orders WHERE user_id = ?显示Query_time: 3.2s,但EXPLAIN显示走索引、Rows_examined只有 12 —— 实际是被UPDATE orders锁住了 -
Lock_time高(比如 2.8s)而Rows_examined低,基本就是锁争用,不是 SQL 本身问题 -
Rows_sent远大于Rows_examined(如 10000 vs 100):说明有大量临时表或排序,需看Extra字段是否含Using filesort或Using temporary
这时不要急着优化 SQL,先用 SHOW ENGINE INNODB STATUS\G 看当前锁等待链。
输出报告里最该盯住的三列指标
pt-query-digest 默认报告每行代表一类指纹化 SQL,关键列含义容易误解:
-
Rank:按总响应时间降序排,但第 1 名未必最该优化——可能只是调用量极大,单次才 50ms -
Response time:格式是3.23s (42%),括号内是占总慢查耗时百分比,这个数字比 Rank 更反映影响面 -
Calls:执行次数,结合Time/call(平均每次耗时)才能判断是“高频轻耗时”还是“低频重耗时”
真正要优先处理的是:Response time % > 10% 且 Time/call > 500ms 的组合。这类查询往往既拖慢整体,又具备明确优化空间(比如加索引、改 JOIN 顺序)。
别漏看底部的 Profile 小节——它把所有慢查按 Query_time、Lock_time、Rows_examined 分桶统计,能快速看出瓶颈集中在哪一环。










