pt-query-digest用于聚合分析慢查询日志,识别拖垮数据库的关键查询类别;需确保slow_query_log=on、log_output=file、long_query_time≤1,并用--filter筛选高危模式,按query_time:sum和rows_examined:sum双维度排序,聚焦fingerprint而非原始sql。

pt-query-digest 不是用来“看日志原文”的,而是把成千上万条 SQL 聚合成几类关键查询,直接告诉你哪一类在拖垮数据库。
确认慢查询日志已开启且阈值合理
没开日志或 long_query_time 设为默认 10 秒,等于基本漏掉所有真实瓶颈。必须先验证:
-
slow_query_log值为ON(不是OFF或空) -
slow_query_log_file指向的路径,MySQL 进程有写权限(常见坑:SELinux 阻止、目录属主不对) -
long_query_time≤1(业务高峰期建议设为0.5,否则大量亚秒级但高频的烂查询会被忽略) -
log_output是FILE(TABLE格式不被pt-query-digest支持)
用 --filter 快速聚焦可疑查询模式
原始日志动辄 GB 级,直接全量分析耗时又干扰判断。用 --filter 提前筛出高危特征:
- 查全表扫描:
pt-query-digest --filter '((event->{Full_scan}||"") eq "yes")' /var/lib/mysql/mysql-slow.log - 查没走索引的 JOIN:
pt-query-digest --filter '((event->{Full_join}||"") eq "yes")' slow.log - 只看某个应用用户:
pt-query-digest --filter '($event->{user} || "") =~ m/^app_user/i' slow.log - 过滤掉健康查询(如健康检查语句):
--filter '$event->{fingerprint} !~ m/SELECT.*FROM health_check/i'
注意:Perl 正则写在单引号里,$event->{key} 中的 key 名必须和日志字段完全一致(大小写敏感),常见字段包括 Full_scan、Query_time、Lock_time。
按 Query_time:sum 排序而非默认排序
默认按总响应时间(Query_time:sum)排是对的,但很多人忽略另一个关键维度:Rows_examined:sum。高 Rows_examined 却低 Query_time 的查询,往往是索引失效+数据量小掩盖了问题——等数据涨十倍就爆炸。
- 看资源消耗大户:
pt-query-digest --order-by 'Rows_examined:sum' slow.log - 对比两个维度:
pt-query-digest --order-by 'Query_time:sum,Rows_examined:sum' slow.log - 避免被“单次超长但极少执行”的查询带偏,加
--limit 20控制输出行数
别跳过 fingerprint 和 report 头部信息
报告开头的 Summary 部分藏着最易被忽略的线索:
- 看
# Profile表里Rank列 —— 排名靠前但Response time占比不到 5% 的,通常不是瓶颈;占比 >30% 的那 1–2 类才值得死磕 - 每类查询下方的
# Query 1块里,fingerprint行显示的是参数化后的模板(如SELECT * FROM orders WHERE status = ? AND created_at > ?),这才是你该拿去 explain 的语句,不是日志里带具体值的那条 -
Count和Exec time的比值异常高(比如 Count=10000,但 Exec time 总和才 0.2s),说明单次极快但调用频次失控,得查应用层是否循环调用
真正卡住系统的,往往不是某条“慢”SQL,而是指纹相同、每秒执行几十次、每次扫几万行的“快”SQL。盯住 fingerprint,而不是原始日志里的某一行。











