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

MySQL sys.schema_table_statistics_with_buffer 怎样定位表级 IO

来源:17golang原创

时间:2026-10-31 23:20:41 335浏览 收藏

遇到“数据库变慢但还不知道是哪张表在制造 IO”时,可以先看 MySQL sys schema 的 schema_table_statistics_with_buffer 视图。它把表级读写请求、读写字节、等待时间,以及 InnoDB 缓冲池相关字段放在一起,适合作为排查候选清单的入口;它记录的是统计视图中的累计口径,不是某一条 SQL 的单次耗时。

官方地址:https://dev.mysql.com/doc/refman/8.4/en/sys-schema-table-statistics-with-buffer.html

本文采用“从粗粒度统计迁移到表级定位”的实战方式,只讨论如何读字段、筛选方向和整理下一步动作,不把静态说明图当成数据库运行截图。

先确认视图和统计口径

这个视图的核心价值是把表名、表级 IO 和 InnoDB buffer pool 信息放在同一条记录里。官方文档说明,视图默认按总等待时间从高到低排列,并通过辅助视图汇总 Performance Schema 的表级 IO 数据。排查前先确认目标实例已经有 sys schema,并把系统库排除,避免把内部对象的活动混入业务表排名。

-- 先看有哪些业务表进入统计视图,避免把系统库混进排查结果
SELECT table_schema, table_name
FROM sys.schema_table_statistics_with_buffer
WHERE table_schema NOT IN ('mysql', 'sys', 'performance_schema', 'information_schema')
LIMIT 20;

这里的结果只说明统计视图当前能看到哪些表,不等于已经找到了根因。还要记录采样时间、实例角色、业务高峰与否,以及是否刚刚清空过 Performance Schema 统计。

业务表、sys表级统计视图、IO字段和缓冲池字段之间关系的静态说明图
图1:结构说明图,展示业务表如何进入 sys 表级统计视图,以及 IO 与缓冲池字段的静态关系,不是数据库运行截图。

用可读视图筛出表级 IO 候选

第一轮排查优先使用不带 x$ 前缀的可读视图。常用字段可以分成三组:rows_fetched、rows_inserted、rows_updated 和 rows_deleted 说明行级活动;io_read_requests、io_read、io_write_requests 和 io_write 说明 IO 量;对应的 *_latency 字段用于观察等待时间方向。

-- 先按读写字节量找出需要继续分析的业务表
SELECT
    table_schema,
    table_name,
    rows_fetched,
    io_read_requests,
    io_read,
    io_write_requests,
    io_write,
    fetch_latency,
    io_read_latency,
    io_write_latency
FROM sys.schema_table_statistics_with_buffer
WHERE table_schema NOT IN ('mysql', 'sys', 'performance_schema', 'information_schema')
ORDER BY io_read + io_write DESC
LIMIT 20;

这条查询回答的是“哪些表值得先看”,而不是“哪条 SQL 一定有问题”。读字节高,可能是大范围读取、缓存未命中或数据访问模式造成;写字节高,可能与批量写入、更新放大或后台任务有关。要继续判断,必须回到语句摘要、索引设计和业务时间窗。

需要精确排序时切换到 x$ 伴随视图

当需要脚本化排序、导出数值或按阈值筛选时,使用 x$schema_table_statistics_with_buffer 伴随视图更合适。可读视图偏向展示,x$ 视图保留更接近原始统计的字段,适合让采集程序自己格式化单位。不要把两个视图的字段值直接混算,先确认采集端对字节、延迟和计数的单位约定。

-- 用 x$ 视图保留原始数值,按总读写量选择候选表
SELECT
    table_schema,
    table_name,
    io_read_requests,
    io_read,
    io_write_requests,
    io_write,
    io_read_latency,
    io_write_latency
FROM sys.x$schema_table_statistics_with_buffer
WHERE table_schema = 'app'
ORDER BY io_read + io_write DESC
LIMIT 20;

如果你的目标是判断等待而不是流量,改用对应的延迟字段排序;如果目标是判断读放大,优先对比读取行数与读取字节。不同指标回答不同问题,不能只凭一列的排名给表加索引或调大缓存。

把 IO 与 InnoDB 缓冲池字段放在一起解释

这个视图的差异化字段是 innodb_buffer_allocated、innodb_buffer_data、innodb_buffer_free、innodb_buffer_pages 和 innodb_buffer_rows_cached。其中,已分配的 buffer bytes、其中的数据 bytes、非数据 bytes、页数量和缓存行数描述的是表在 InnoDB 缓冲池中的统计关系。它们可以帮助你判断“表很热但主要在缓存中”还是“表的读取压力和缓存占用同时偏高”,但不能单独证明一次查询发生了磁盘随机读。

-- 同时查看业务表的读写压力与 InnoDB 缓冲池占用字段
SELECT
    table_schema,
    table_name,
    io_read,
    io_write,
    io_read_latency,
    io_write_latency,
    innodb_buffer_allocated,
    innodb_buffer_data,
    innodb_buffer_free,
    innodb_buffer_pages,
    innodb_buffer_rows_cached
FROM sys.schema_table_statistics_with_buffer
WHERE table_schema = 'app'
ORDER BY io_read + io_write DESC
LIMIT 20;

读写量、等待时间和缓冲池字段要组合看:读写量高但等待低,可能只是访问频繁且缓存有效;读写量不高但等待明显,可能需要转向锁等待、磁盘或语句级分析;缓冲池占用高也不代表应该立即缩小表或清理缓存。

表级读写量、等待时间、InnoDB缓冲池占用和下一步分析边界的静态关系图
图2:边界说明图,展示 IO 量、延迟、缓冲池字段与下一步分析之间的关系,不是运行结果或性能截图。

用迁移式清单收尾,避免误判累计统计

观察方向先看字段下一步
读请求或读字节高io_read_requests、io_read、rows_fetched结合语句摘要、过滤条件和索引覆盖分析扫描范围
写请求或写字节高io_write_requests、io_write、更新/删除行数区分业务批量写入、后台任务和更新放大
等待时间高fetch_latency、io_read_latency、io_write_latency转向锁等待、磁盘延迟和语句级耗时定位
缓冲池字段高innodb_buffer_allocated、innodb_buffer_data结合实例内存、热表分布和采样窗口判断缓存压力

从旧的“只看实例总 IO”迁移到表级定位时,至少保存四项上下文:采样时间、统计是否重置、表所属实例角色、筛选条件。这样下一次比较才知道变化来自业务流量,还是来自统计窗口变化。这个视图适合定位候选,不替代 EXPLAIN、语句摘要或真实压测。

相关问题

为什么表级统计和某条 SQL 的耗时对不上?

表级视图聚合的是一段时间内的表活动与等待,单条 SQL 的耗时还会受到连接、锁、排序、网络和执行计划影响。两者应作为不同层级的线索交叉使用。

应该直接查 sys 视图还是 x$ 视图?

人工阅读和初步排查使用 sys 视图;需要稳定数值、阈值筛选或脚本导出时使用对应的 x$ 视图,并在采集程序中统一单位。

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