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

MySQL table_io_waits_summary_by_index_usage 中 NULL 索引名代表什么

来源:17golang原创

时间:2026-11-02 05:48:52 404浏览 收藏

MySQL table_io_waits_summary_by_index_usage 中 NULL 索引名代表什么

在 MySQL Performance Schema 的 table_io_waits_summary_by_index_usage 中看到 INDEX_NAME = NULL,通常不要马上下结论说“这张表没有索引”。它表示这组表 I/O 等待没有归属到某个具体索引;其中,插入操作会计入 NULL 这一组。真正判断索引是否被使用,需要把 NULL、PRIMARY 和具体二级索引放在同一张表的统计中比较。

本文只讨论这个字段的语义、查询方式和观察窗口,不把静态查询示例当作线上执行结果。

先把 NULL、PRIMARY 和“没有索引”分开

table_io_waits_summary_by_index_usage 按表索引聚合表 I/O 等待。INDEX_NAME = PRIMARY 表示事件归属于主键索引;具体名称表示归属于对应二级索引;NULL 则表示没有可关联的索引名。官方文档还特别说明,插入操作计入 INDEX_NAME = NULL。

MySQL 表 I/O 按 PRIMARY、二级索引和 NULL 分组的静态关系说明图
图1:表 I/O 汇总按索引分组的静态说明图,NULL 组与 PRIMARY、二级索引是并列统计,不是运行截图。

因此,NULL 行可能来自写入路径,也可能来自没有被具体索引标识的表 I/O 事件。它不是执行计划的替代品,也不能单独证明查询走了全表扫描。

先按表名查看所有索引分组

排查时先缩小到一个 schema 和表,再保留 INDEX_NAME、读取次数和等待时间。下面的查询只读取汇总表,不改变采集配置。

-- 中文注释:按表和索引分组,先看 NULL、PRIMARY 与二级索引的完整分布
SELECT
    OBJECT_SCHEMA,
    OBJECT_NAME,
    INDEX_NAME,
    COUNT_STAR,
    COUNT_READ,
    COUNT_FETCH,
    SUM_TIMER_WAIT
FROM performance_schema.table_io_waits_summary_by_index_usage
WHERE OBJECT_SCHEMA = 'app'
  AND OBJECT_NAME = 'orders'
ORDER BY SUM_TIMER_WAIT DESC;

这里最重要的是保留 INDEX_NAME 原值,不要用 COALESCE(INDEX_NAME, '无索引') 后再作第一轮判断,否则会把“没有索引归属”和“表没有索引”混成一个概念。

怎样解释 NULL 行里的数字

如果 NULL 行的 COUNT_STAR 很高,先看业务操作是否包含大量 INSERT。插入会计入 NULL 组,所以这类数字可能只是写入量的反映。COUNT_READ、COUNT_FETCH 和 SUM_TIMER_WAIT 应结合操作类型、时间窗口和具体 SQL 一起解释,不能仅凭某一列的绝对值判断索引质量。

可以把结果按索引名做一个更适合阅读的投影,但建议保留原始值:

-- 中文注释:仅用于展示分组标签,原始 INDEX_NAME 仍应保留在明细查询中
SELECT
    OBJECT_SCHEMA,
    OBJECT_NAME,
    CASE
        WHEN INDEX_NAME IS NULL THEN 'NULL:未归属具体索引'
        ELSE INDEX_NAME
    END AS index_group,
    COUNT_STAR,
    COUNT_READ,
    COUNT_FETCH,
    SUM_TIMER_WAIT
FROM performance_schema.table_io_waits_summary_by_index_usage
WHERE OBJECT_SCHEMA = 'app'
  AND OBJECT_NAME = 'orders'
ORDER BY COUNT_STAR DESC;

这个标签只是展示层解释,不会改变 Performance Schema 的统计含义。

建立观察窗口,再决定是否需要复查

汇总表保存的是累计信息。若需要观察一次发布或一段压测,可以先记录当前值,再清空指定汇总表的统计列,之后在固定窗口内采集。执行前要确认账号权限、采集窗口和业务影响。

-- 中文注释:重置表 I/O 汇总列,之后只观察新的时间窗口
TRUNCATE TABLE performance_schema.table_io_waits_summary_by_index_usage;

-- 中文注释:窗口结束后读取各索引组,比较新的读取次数与等待时间
SELECT
    OBJECT_SCHEMA,
    OBJECT_NAME,
    INDEX_NAME,
    COUNT_READ,
    COUNT_FETCH,
    SUM_TIMER_WAIT
FROM performance_schema.table_io_waits_summary_by_index_usage
WHERE OBJECT_SCHEMA = 'app'
  AND OBJECT_NAME = 'orders'
ORDER BY SUM_TIMER_WAIT DESC;
MySQL NULL 索引组从写入统计到复查窗口的判读边界说明图
图2:NULL 索引组的判读边界说明图,展示静态分析路径,不是数据库控制台截图或真实运行证据。

常见误区

误区更准确的判断
看到 NULL 就说表没有索引NULL 说明该事件没有具体索引归属;先结合表结构与操作类型。
把 NULL 行当成全表扫描次数Performance Schema 汇总不是执行计划,需结合 EXPLAIN 或实际 SQL 另行判断。
直接比较累计值先明确采集起点和窗口,必要时重置汇总后再比较。

小结

INDEX_NAME = NULL 的核心含义是“这组表 I/O 等待没有对应的具体索引名”,而插入操作会计入这组。排查时保留 NULL、PRIMARY 和二级索引分组,先按表查看,再结合操作类型和固定观察窗口解释数字。只有当这些信息与表结构、SQL 和执行计划互相印证时,才适合继续讨论索引设计。

相关问题

NULL 行是不是一定代表全表扫描?

不是。它不是执行计划字段,不能单独推出全表扫描。

为什么 INSERT 会出现在 NULL 分组?

因为插入统计按官方定义计入 INDEX_NAME = NULL,不代表插入路径异常。

怎样避免累计数据影响判断?

固定观察窗口,必要时重置对应汇总表,再比较同一窗口内的计数和等待时间。

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