按摘要找重查询是什么
performance_schema 的 events_statements_summary_by_digest 表按语句模板聚合统计(常量被归一化占位),给出调用次数、累计耗时与扫描行数,是 MySQL 8 上不翻慢日志就能找出主要负载的手段。它与 PostgreSQL 的 pg_stat_statements 定位相同:按模板排名,看谁占用了最多时间。使用前必须记住两点——计时单位是皮秒,换算要除以 1e12;统计自实例启动累计,压测前应清零。
基本信息
| 适用平台 | MySQL 8.0(5.7 也有该表,字段略有差异) |
|---|---|
| 表名 | performance_schema.events_statements_summary_by_digest |
| 计时单位 | 皮秒:除以 1e12 得秒,除以 1e9 得毫秒 |
| 统计窗口 | 自实例启动累计,可 TRUNCATE 清零 |
| 查询为空时 | 检查 setup_consumers 中 statements_digest 是否为 ENABLED(默认已启用) |
典型使用场景
- 找出占用累计时间最多的 SQL 模板,确定优化顺序
- 压测前后对比:先清空统计再跑同一负载
- 定位调用次数异常高的语句,排查应用循环查询
- 结合累计扫描行数判断是否长期在做大范围扫描
- 与慢查询日志互补:日志看尖峰,摘要看整体占比
排名查询
排名查询
SELECT LEFT(digest_text, 80) AS sql_text,
count_star, # 模板被执行次数
ROUND(sum_timer_wait / 1000000000000, 2) AS total_sec, # 皮秒转秒
ROUND(avg_timer_wait / 1000000000, 2) AS avg_ms, # 皮秒转毫秒
sum_rows_examined, # 累计扫描行数
ROUND(sum_rows_examined / NULLIF(count_star, 0), 1) AS rows_per_call
FROM performance_schema.events_statements_summary_by_digest
ORDER BY sum_timer_wait DESC
LIMIT 10;
-- 压测或变更前清零,让数据只对应观察窗口
TRUNCATE TABLE performance_schema.events_statements_summary_by_digest;换一个排序视角
换一个排序视角
# 按平均耗时找「单次很慢」的语句,过滤掉样本过少的模板
SELECT LEFT(digest_text, 80) AS sql_text,
count_star,
ROUND(avg_timer_wait / 1000000000, 2) AS avg_ms,
sum_rows_sent
FROM performance_schema.events_statements_summary_by_digest
WHERE count_star > 100
ORDER BY avg_timer_wait DESC
LIMIT 10;关键列读法
| 列 | 含义 | 关注点 |
|---|---|---|
| digest_text | 参数归一化后的语句模板 | 常量被替换为 ?,看不到具体参数值 |
| count_star | 执行次数 | 高频小语句会累积出很高的总耗时 |
| sum_timer_wait | 累计耗时(皮秒) | 排名主依据,注意单位换算 |
| avg_timer_wait | 平均耗时(皮秒) | 反映单次代价 |
| sum_rows_examined | 累计扫描行数 | 与调用次数对比可看出扫描放大倍数 |
两种排序各有用途:按 sum_timer_wait 找总耗时榜首,对应「优化收益最大」的语句;按 avg_timer_wait 找单次最慢的语句,对应影响用户体验的慢点,通常需要分别处理。
把 sum_timer_wait 的数字直接当毫秒解读会得出离谱结论:performance_schema 的计时单位是皮秒,换算公式固定为除以 1e12 得到秒。