首页/数据/SQL 速查/Handler 与 InnoDB 行计数解读
性能与执行计划72 条

Handler 与 InnoDB 行计数解读

Handler_read_rnd_next、Innodb_rows_read 等计数从扫描行为侧面验证 EXPLAIN 的结论,用增量对比才有意义。

SQL 速查数据更新于 2026-10-13

这组计数看什么

MySQL 的 Handler 与 InnoDB 状态计数从扫描行为侧面反映查询是怎么读数据的:按索引键定位、按索引顺序扫描、还是全表逐行读。它不能告诉你哪条 SQL 慢,但能在 EXPLAIN 之外给出「实际读了多少行」的证据——前提是用两次快照的差值来判断。

基本信息

适用平台MySQL(SHOW GLOBAL STATUS 或 performance_schema.global_status)
Handler_read_key按索引键定位的读取次数
Handler_read_next按索引顺序读下一行(范围或索引扫描)
Handler_read_rnd_next全表顺序读下一行,持续增长提示表扫描
Innodb_rows_readInnoDB 读取行数总量
判读方法取两次快照做差,绝对值没有意义

典型使用场景

  • 验证某条查询到底是走索引还是扫全表
  • 压测或跑批前后对比扫描量增量
  • 排查周期性任务是否引入了全表扫描
  • 解释「计划说走索引、实际却很慢」的差异
  • 长期监控全表扫描趋势,指导加索引

取数与对比

取数与对比
SHOW GLOBAL STATUS
WHERE Variable_name IN ('Handler_read_first','Handler_read_key',
  'Handler_read_next','Handler_read_rnd_next','Innodb_rows_read','Queries');

-- 也可以用 performance_schema 过滤同一组变量
SELECT VARIABLE_NAME, VARIABLE_VALUE
FROM performance_schema.global_status
WHERE VARIABLE_NAME LIKE 'Handler_read%'
   OR VARIABLE_NAME = 'Innodb_rows_read';

-- 压测或跑批前后各取一次快照,用差值判断扫描量

计数逐项读法

计数统计什么异常信号
Handler_read_key按索引键定位的次数远低于扫描次数说明索引没被用上
Handler_read_next按索引顺序读下一行结合范围条件判断扫描区间大小
Handler_read_rnd_next全表顺序读下一行持续增长说明在做表扫描
Innodb_rows_readInnoDB 读取行数总量与返回行数差距大说明读了多余数据
Queries执行的语句总数用来把增量归一化成每次查询的量
这些都是自启动以来的累计值:判断「现在是否在扫表」要看两次快照的差值,绝对值大可能只是很久以前跑过一次批量任务。
Handler_read_rnd_next 只统计行读取动作,不代表磁盘 IO:是否命中缓冲池要看 InnoDB 的物理读计数,两套指标要分开解读。

易错点

  • 用累计值直接下结论:高计数可能来自历史上一次批量任务,必须用间隔增量判断
  • 把 Handler_read_rnd_next 当作磁盘读:它只统计行读取动作,是否落盘要看 InnoDB 物理读计数
  • 只看总数不分摊到查询数:用 Queries 归一化后才好在不同负载之间比较读放大程度
  • 忽略排序与临时表带来的额外读取:文件排序与临时表会让计数明显抬升,要结合执行计划一起看
  • 在生产高峰期做长窗口对比:业务结构变化会污染差值,尽量在同类负载下比较

数据来源与参考

  • MySQL 8.0 Reference Manual §5.1.10 Server Status Variables
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌