查不到慢查询需先确认performance_schema启用且statements_digest消费者已开启,digest_text为标准化模板并可能截断,avg_timer_wait单位为皮秒需换算,performance_schema_digests_size溢出会导致统计丢失。

查不到慢查询?先确认 performance_schema 是否启用且采集开启
默认 mysql 8.0 虽启用 performance_schema,但 events_statements_summary_by_digest 对应的消费者可能被关掉。只开引擎不等于能查到语句摘要。
-
select * FROM performance_schema.setup_consumers WHERE NAME = 'statements_digest';—— 必须为ENABLED -
SELECT * FROM performance_schema.setup_instruments WHERE NAME = 'statement/sql/select' AND ENABLED = 'NO';—— 若大量NO,说明具体语句类型未采集,需用UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'statement/%';批量打开(注意性能影响) - MySQL 5.7 默认关闭
statements_digest消费者,必须手动开;8.0 默认开,但某些云厂商镜像会改配置
digest_text 被截断?别信它显示的 SQL 片段
digest_text 是标准化后的模板,不是原始 SQL,且长度上限固定(MySQL 8.0 为 1024 字符)。它会把常量、表别名、空格全抹掉,还可能截断复杂子查询或长列名列表。
- 看到
SELECT ... FROM t1 JOIN t2 ... WHERE ...后面带省略号?大概率关键条件已被砍掉 - 真正要看原始语句,得结合
DIGEST值去查events_statements_history_long(如果开了)或搭配slow_query_log交叉验证 - 不要用
digest_text直接判断是否“用了索引”——它不保留USE INDEX、FORCE INDEX等提示
为什么 avg_timer_wait 和实际执行时间差十倍?看单位和归一化逻辑
avg_timer_wait 单位是皮秒(picosecond),不是毫秒;而且它是对所有执行样本取平均,包含大量毫秒级快查,会严重拉低均值。单次慢查可能被淹没。
- 换算:除以
1000000000得纳秒,再除1000000才是毫秒 —— 即avg_timer_wait / 1000000000000 - 更实用的是看
sum_timer_wait+count_star,算出总耗时占比;或者直接筛max_timer_wait > 1000000000000(即 >1s)的 digest - 注意:若语句含网络等待、锁等待(如
Waiting for table metadata lock),这部分也计入timer_wait,但不属于纯执行时间
聚合不准?检查 performance_schema_digests_size 是否溢出
这个变量控制 digest 缓存槽位数,默认 200(5.7)或 10000(8.0)。一旦实际 distinct SQL 模板数超限,新语句就会挤掉旧 digest,导致统计丢失、count_star 归零、甚至 digest_text 变成 NULL。
- 查当前使用率:
SELECT COUNT(*) FROM performance_schema.events_statements_summary_by_digest; - 查配置上限:
SHOW VARIABLES LIKE 'performance_schema_digests_size'; - 溢出后现象:高频小查询突然消失、
SCHEMA_NAME为空、count_star波动剧烈 —— 不是数据不准,是根本没存进去 - 调大需重启(5.7)或动态设(8.0+,但有内存代价),建议按 QPS × 300 秒预估活跃 digest 数
事情说清了就结束。digest 分析本质是采样+聚合,不是全量日志;它快、轻量,但也因此丢细节、受配置制约。真要定位某条慢语句,它只是起点,不是终点。