1. 概述
pt-query-digest 是 Percona Toolkit 中最强大、最常用的 MySQL/MariaDB 性能分析工具。它的核心作用是将杂乱的慢查询日志(Slow Query Log)、通用日志(General Log)甚至实时流量(tcpdump/PROCESSLIST)转化为可读性极强的统计报告,帮助你快速定位"最耗资源"的 SQL 语句。
核心功能
- 指纹化(Fingerprinting):自动将具体的 SQL 语句参数化(例如将 SELECT * FROM users WHERE id=1 和 id=2 归为一类 SELECT * FROM users WHERE id=?),从而统计同类查询的总耗时和频率。
- 多维度排序:默认按总响应时间排序,也可以按执行次数、锁等待时间、IO 等待时间等排序。
- 多数据源支持:
- 慢查询日志文件 (slow.log)
- 通用日志 (general.log)
- MySQL 进程列表 (SHOW PROCESSLIST)
- TCP 抓包数据 (tcpdump)
- Binary Log (需先用 mysqlbinlog 转为文本)
2. 安装方式
常用方式 直接下载单文件
### step 1 下载脚本 在终端执行以下命令(确保服务器能访问外网)
wget https://www.percona.com/get/pt-query-digest
### step 2 赋予执行权限
chmod +x pt-query-digest
### Step 3 移动到系统路径(可选)
## 为了方便在任何目录下都能直接输入 pt-query-digest 命令,建议将其移动到 /usr/local/bin 或 /usr/bin
sudo mv pt-query-digest /usr/local/bin/
### Step 4 验证安装
##输入以下命令查看版本,若输出版本号则成功:
pt-query-digest --version
通过包管理器安装
如果你不仅需要 pt-query-digest,还需要 Percona Toolkit 中的其他工具(如 pt-online-schema-change, pt-table-checksum 等),建议直接安装整个工具包。
需要先配置 Percona 的 YUM 源,然后安装:
# 安装 Percona 仓库配置包 (以 CentOS 7/8 为例,具体版本请参照官网)
sudo yum install https://repo.percona.com/yum/percona-release-latest.noarch.rpm
# 刷新缓存并安装
sudo yum makecache fast
sudo yum install percona-toolkit
安装时常见问题与依赖处理
如果在运行 pt-query-digest 时遇到类似 Can't locate DBI.pm 或 Can't locate Digest/MD5.pm 的错误,说明缺少 Perl 模块。
sudo yum install perl-DBI perl-Digest-MD5 perl-Time-HiRes perl-Term-ReadKey
3. 常用参数速查表
| 参数 | 说明 | 示例 |
|---|---|---|
--since |
只分析指定时间之后的日志 | --since '2h' (最近2小时), --since '2026-03-01 10:00:00' |
--until |
只分析指定时间之前的日志 | --until '1h' |
--limit |
限制输出的报告条目数 | --limit 5 (只看前5名) |
--order-by |
排序依据 | --order-by query_time (默认), --order-by rows_examined |
--filter |
过滤特定语句 (Perl 表达式) | --filter '$event->{db} eq "production"' |
--output |
输出格式 | --output json, --output csv |
--no-report |
不生成详细报告,仅生成摘要或存库 | 配合 --review 使用 |
4. 输出报告内容格式
报告通常分为三个主要部分:总体统计(Overall)、查询概要(Profile)和详细查询报告(Query Report)。
4.1 总体统计 (Overall)
这是报告的开头部分,展示了日志文件的全局概况。
# Rank Query ID Response time Calls R/Call V/M Item
# ==== ================= ============== ===== ======= ===== =====================================
# 1 0x8F2A3B1C... 120.5s (90.2%) 100 1.205s 0.02 SELECT users WHERE ...
# 2 0x1B3C4D5E... 10.2s (7.6%) 50 0.204s 0.01 UPDATE orders SET ...
# 3 0x9A8B7C6D... 2.9s (2.2%) 200 0.015s 0.00 INSERT INTO logs ...
关键字段解析:
- Rank: 排名。默认按总响应时间从高到低排序(最耗时的排第一)。
- Query ID: 查询指纹的哈希值。相同的 SQL 结构(参数不同)会有相同的 ID。
- Response time:
- 120.5s: 该类查询消耗的总时间。
- (90.2%): 最重要指标。表示该类查询占总耗时量的百分比。如果前几名加起来超过 80%,优化它们就能解决大部分性能问题。
- Calls: 执行次数。
- R/Call (Response time per Call): 平均每次执行的耗时。如果这个值很大,说明单次查询就很慢;如果很小但总时间长,说明是频率太高(如循环查询)。
- V/M (Variation to Mean): 方差与均值的比率。
- 值越接近 0,说明执行时间很稳定。
- 值越大(如 > 1),说明执行时间波动极大(有时快,有时极慢),可能涉及锁等待或资源争抢。
- Item: 该类别的代表性 SQL 语句摘要(已参数化)。
4.2 查询概要 (Profile)
这部分以表格形式展示了更细致的统计分布,帮助你判断是"偶尔慢"还是"一直慢"。
# Rank Query ID Response time Calls R/Call Row examine/d Row send/d Version
# ==== ================= ============== ===== ======= ============= ========== =======
# 1 0x8F2A3B1C... 120.5s (90.2%) 100 1.205s 1.2M/12k 100/1 5.7.25
关键指标解读:
- Row examine/d (Rows Examined per call): 平均每次查询扫描的行数。
- 优化重点:如果扫描行数(examine)远大于返回行数(send),例如扫描 100 万行只返回 1 行,通常意味着缺少索引或索引失效。
- Row send/d (Rows Sent per call): 平均每次查询返回给客户端的行数。
- Version: 执行该查询时的 MySQL 版本(如果日志中包含)。
4.3 详细查询报告 (Query Report) - 核心部分
这是最有价值的部分,针对排名前几位的 SQL 进行深度剖析。
A. 统计分布 (Statistics)
# Statistics
# Count : 100
# Exec time: 120s total, 1s avg, 2s min, 50s max, 95th percentile: 5s, 99th: 10s
# Lock time: 0.5s total, 5ms avg, 0s min, 100ms max
# Rows sent: 100 total, 1 avg
# Rows exam: 120M total, 1.2M avg
# Sizes: 0 bytes total, 0 bytes avg
- Exec time (执行时间):
- avg: 平均值。
- min / max: 最小/最大耗时。如果
max远大于avg,需排查偶发卡顿。 - 95th percentile (P95): 95% 的请求都在这个时间内完成。比平均值更有参考价值,因为它排除了极端异常值的影响。
- Lock time (锁等待时间): 如果锁等待时间占比很高,说明存在严重的锁竞争(死锁或长事务阻塞)。
- Rows exam vs Rows sent: 再次强调扫描行数与返回行数的比例,确认索引效率。
B. 指纹化 SQL (Fingerprint)
# Fingerprint
SELECT * FROM users WHERE id = ? AND status = ?
- 具体的数字/字符串被替换为 ?。这告诉你这类查询的结构。
C. 具体示例 (Example)
# Example
SELECT * FROM users WHERE id = 12345 AND status = 'active'
- 给出一个真实的执行样本,你可以直接拿这条 SQL 去数据库执行
EXPLAIN分析执行计划。
5. 使用案例
5.1 直接分析生成的慢日志文件,输出报告到终端:
pt-query-digest /var/log/mysql/slow.log
5.2 只分析最近 1 小时的日志,并按执行次数排序:
pt-query-digest --since '1h' --order-by query_count /var/log/mysql/slow.log
5.3 忽略执行时间小于 1 秒的查询:
pt-query-digest --filter '($event->{exec_time} || 0) > 1' slow.log
5.4 输出为 JSON 格式(方便程序处理):
pt-query-digest --output json slow.log
5.5 只关注扫描行数最多的 SQL(而不是耗时最长的):
pt-query-digest --order-by rows_examined:sum slow.log
5.6 将分析结果存入数据库(长期追踪):
将分析结果写入 MySQL 表中,以便通过 SQL 查询历史趋势或集成到监控大屏
pt-query-digest --review h=localhost,D=percona,t=query_review /var/log/mysql/slow.log
注意:首次运行需加 --create-review-table 自动建表
6. 其它用途
6.1 实时监控当前运行的查询
不依赖日志文件,直接抓取当前数据库正在执行的语句进行分析(适合突发性能问题):
pt-query-digest --processlist h=localhost,u=用户名,p=用户的_password --interval 5
- --interval 5:每 5 秒采样一次。
6.2 分析 tcpdump 抓取的流量
如果你无法开启慢日志,但能抓包,可以分析网络流量:
# 1. 抓取流量 (假设端口 3306)
tcpdump -s 65535 -x -nn -q -i eth0 port 3306 -w mysql.tcpdump
# 2. 分析抓包文件
pt-query-digest --type tcpdump mysql.tcpdump