pt-query-digest的核心价值在于指纹化聚合与多维统计,而非简单筛选最慢sql;它将参数不同的同类查询归为一类(如select * from orders where user_id = ?),并统计总耗时、扫描行数、锁等待等关键指标,精准识别高频低效的“沉默杀手”。

pt-query-digest 不是用来“挑出最慢的那条 SQL”就完事的工具——它真正价值在于帮你识别重复出现、高资源消耗、但被掩盖在日志洪流里的性能杀手。直接看原始日志,你可能只看到几十条 SELECT <em> FROM orders WHERE user_id = 12345</em>,每条执行 0.8 秒;而 pt-query-digest 会把它们聚合成一条指纹 SELECT FROM orders WHERE user_id = ?,并告诉你:这类查询共执行 2376 次,总耗时 1892 秒,平均每次 0.796 秒,但扫描了 1200 万行,且 99% 的执行都走了全表扫描。
为什么不能只用 mysqldumpslow?
它只能按字面排序,无法指纹化,更不会统计锁等待、扫描行数、索引使用状态这些关键指标。比如两条 SQL:SELECT * FROM t WHERE id = 1 和 SELECT * FROM t WHERE id = 2,mysqldumpslow 当作两条独立记录;而 pt-query-digest 视为同一类,暴露出“这个查询结构本身就有问题”。
分析前必须确认的三件事
很多报告跑出来全是空或不准,往往卡在这三步:
-
slow_query_log必须是ON,且slow_query_log_file路径可读(用ls -l /var/log/mysql/mysql-slow.log看权限) -
long_query_time建议设为1或更低(如0.1),否则大量“亚慢查询”漏掉 - 日志里得有真实慢查询——如果
tail -n 20 /var/log/mysql/mysql-slow.log全是空行或# Time:开头没跟 SQL,说明日志根本没写入,先查 MySQL 配置是否生效(SHOW VARIABLES LIKE 'slow_query%')
关键参数怎么选:不是所有选项都该开
默认命令 pt-query-digest /var/log/mysql/mysql-slow.log 只输出摘要,实际排查要加参数:
- 定位高频低效查询:
--filter '$event->{Full_scan} eq "yes"'—— 直接筛出全表扫描的语句,比翻报告快得多 - 聚焦最近问题:
--since=1h或--since='2026-07-01 15:00:00',避免被历史噪音干扰 - 排除干扰项:
--limit 20控制输出行数;--no-report加--review才写入数据库表,避免误操作 - 别轻易用
--create-review-table:它会在目标库建表,若权限不足或表已存在会报错,先手动建好query_review表更稳妥
报告里最容易被忽略的三列指标
打开生成的文本报告,第一眼别只盯 Query_time 总和,这三列才是判断“是不是真杀手”的核心:
-
Rows_examined:单次扫描行数 × 执行次数 = 实际 I/O 压力。值远大于结果行数(比如查 1 行却扫 10 万行),基本等于没走对索引 -
Lock_time:如果占比超过Query_time的 20%,说明不是 SQL 慢,是锁竞争严重(比如事务没提交、长事务阻塞) -
Rows_sentvsRows_examined比值:若Rows_sent是 1 而Rows_examined是 50000,大概率是ORDER BY + LIMIT没走索引,或者WHERE条件没命中索引最左前缀
真正的瓶颈往往藏在“看起来不慢但高频扫描”的查询里,而不是那条执行 5 秒的孤立 SQL。用 pt-query-digest 时,重点不是找最大值,而是找那些 Rows_examined 高、Exec_count 高、Query_time 中等但累加起来吃掉 70% 总耗时的“沉默杀手”——它们才最值得优先优化。











