登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  MySQL

MySQL performance_schema 语句 digest 如何定位慢 SQL 模式

来源:17golang原创

时间:2026-09-14 22:42:51 284浏览 收藏

如果业务只说“数据库最近变慢”,先别急着给某一条 SQL 加索引。MySQL 的 Performance Schema 可以把形态相同、参数不同的语句聚成 digest,再用总耗时、平均耗时、执行次数和扫描行数区分“最费资源”和“单次最慢”。真正值得先处理的,通常是排名靠前且能拿到样本 SQL 的模式。

官方文档入口:https://dev.mysql.com/doc/refman/8.4/en/

要点速览
  • SCHEMA_NAME + DIGEST 是主要聚合边界,DIGEST_TEXT 是规范化后的语句模式。
  • SUM_TIMER_WAIT 找工作量贡献,AVG_TIMER_WAIT 看单次延迟,不能只盯一个排序。
  • DIGEST IS NULL、容量上限和采样文本都要复核,否则排名可能失真。

先把 digest 视为“语句模式”,再选统计口径

digest 不是原始 SQL 日志,而是 Performance Schema 对已结束语句做的汇总。相同 schema 下,字面量不同但结构相近的查询会落到同一个语句模式;因此它适合回答“应用反复执行哪类 SQL”,不适合直接回答“某一次请求究竟传了什么值”。

MySQL performance_schema digest 按 schema、语句模式和统计字段聚合的静态结构框图
图1:操作示意图,查看 schema 与 digest 聚合边界,以及语句模式和耗时统计字段的静态关系。

COUNT_STAR 表示执行次数,SUM_TIMER_WAIT 表示累计等待,AVG_TIMER_WAIT 表示平均等待,MAX_TIMER_WAIT 则提醒你是否存在长尾。按总耗时排序适合先找“整体最贵”的模式;按平均耗时排序才更接近“单次请求很慢”的问题。

用一条查询先找出最值得处理的慢 SQL 模式

下面的查询把 Performance Schema 的计时字段换算为毫秒,并把扫描量、临时表和样本 SQL 一并取出。示例只读汇总表,不会在本机运行,也不应把示例结果误当成你的线上数据。

SELECT
  SCHEMA_NAME,
  DIGEST,
  DIGEST_TEXT,
  COUNT_STAR,
  ROUND(SUM_TIMER_WAIT / 1000000000000, 2) AS total_ms,
  ROUND(AVG_TIMER_WAIT / 1000000000000, 2) AS avg_ms,
  ROUND(MAX_TIMER_WAIT / 1000000000000, 2) AS max_ms,
  SUM_ROWS_EXAMINED,
  SUM_ROWS_SENT,
  SUM_CREATED_TMP_DISK_TABLES,
  QUERY_SAMPLE_TEXT,
  FIRST_SEEN,
  LAST_SEEN
FROM performance_schema.events_statements_summary_by_digest
WHERE DIGEST IS NOT NULL
-- 先按累计耗时找工作量贡献最大的语句模式
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 20;

这里的排序口径很关键:高频但每次只慢一点的 SQL,可能总耗时最高;低频但单次很慢的 SQL,则可能在 avg_msmax_ms 排名靠前。SUM_ROWS_EXAMINEDSUM_ROWS_SENT 的差距很大时,通常值得再看过滤条件、索引选择和回表成本。

从排名到定位:用样本 SQL 和边界字段复核

拿到候选 digest 后,先看 DIGEST_TEXT 了解模式,再看 QUERY_SAMPLE_TEXT 取得一个实际见过的样本。样本只用于帮助你做 EXPLAIN 或回到应用调用链复核,不能代表该 digest 的所有参数分布。

MySQL digest 总耗时、平均耗时、执行次数、扫描量与样本 SQL 的定位关系静态框图
图2:结果示意图,比较总耗时、平均耗时、执行次数、扫描量和样本 SQL 的静态定位关系。

可以把候选分成三类:总耗时高,优先处理整体资源贡献;平均耗时和最大耗时高,优先检查长尾与锁等待;扫描量高但返回行少,优先核对索引和过滤条件。若要观察某个 digest 的更细粒度仪表,MySQL 的 sys schema 还提供 ps_trace_statement_digest(),但它仍然受 Performance Schema 已采集数据和权限影响。

别让 digest 容量和采样误导判断

digest 汇总表有容量上限。新模式无法进入正常行时,可能汇总到 SCHEMA_NAMEDIGEST 都为 NULL 的 catch-all 行;还应留意 Performance_schema_digest_lost。如果这类行占比明显,先调整启动时的 performance_schema_digests_size,再谈排名。

做一次可比较的观察时,可以在明确的低峰窗口清空 digest 汇总,再让固定业务流量运行一段时间:

TRUNCATE TABLE performance_schema.events_statements_summary_by_digest;
-- 清空当前 digest 窗口;生产环境先确认权限、采样时段和回滚安排
SHOW GLOBAL STATUS LIKE 'Performance_schema_digest_lost';

清空后不要立刻把空表当成“没有慢 SQL”,要等目标流量重新产生统计。最终优化动作仍需结合 EXPLAIN、锁等待、索引使用和应用侧延迟验证;digest 负责缩小范围,不替你做完整执行计划分析。

相关问题

为什么总耗时最高的 SQL 不一定单次最慢?

因为总耗时约等于执行次数与平均耗时的共同结果。高频查询即使单次不慢,也可能贡献最多累计等待。

DIGEST_TEXT 和 QUERY_SAMPLE_TEXT 有什么区别?

DIGEST_TEXT 用来描述归一化后的模式,QUERY_SAMPLE_TEXT 是该模式实际见过的一个样本,后者更适合拿去做代表性检查。

看到 DIGEST 为 NULL 要不要直接优化?

不要。先检查 digest 表容量和丢失计数;NULL 行混合了未能单独建行的模式,不能作为一条具体 SQL 的优化对象。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>