Extra列出现Using MRR表示启用了MRR优化,将随机回表转为顺序回表;但若read_rnd_buffer_size过小或结果集行数太少(默认约10行以下),MRR实际会退化为普通回表。
extra 列出现 using mrr,说明 mysql 在这条查询中启用了 multi-range read 优化,正在把原本的随机回表转为顺序回表——但这不等于性能一定变好,得结合执行计划和实际 i/o 行为一起看。
为什么 Using MRR 只出现在 Extra 里,却不一定真起效?
MRR 是优化器在“计划阶段”打的一个标记,表示它打算用 MRR 流程;但真正执行时是否走 MRR,取决于 runtime 阶段的缓冲区、数据分布和成本估算。
-
read_rnd_buffer_size太小(默认 256KB),收集不到足够多的主键值就触发回表,MRR 实际退化成普通回表 - 预估结果集行数太少(默认约
- 虽然显示
Using MRR,但Handler_read_rnd_next没下降,反而Handler_read_next上升,说明顺序读没压住随机读,MRR 实际未生效 - 覆盖索引查询(
Using index)不会触发 MRR——根本不需要回表,Using MRR不会出现
Using index condition; Using MRR 这种组合意味着什么?
这是 ICP(Index Condition Pushdown)和 MRR 同时参与的典型信号,常见于带范围条件的 LIKE 或函数索引场景。ICP 先在存储引擎层过滤二级索引元组,MRR 再对剩下的主键做排序回表。
- ICP 减少了传给 Server 层的索引行数,MRR 减少了回表时的磁盘随机访问次数
- 但二者都依赖二级索引:如果
key_len显示只用到联合索引前缀,后缀字段被下推过滤,那Using index condition就是 ICP 起效了 - 若
EXPLAIN FORMAT=JSON中"using_mrr": true且"mrr_cost"字段存在数值,才确认 MRR 被纳入成本决策
怎么验证 MRR 真正在干活,而不是挂个名?
光看 EXPLAIN 不够,得查运行时行为和优化器内部决策。
- 执行前先
FLUSH STATUS,再跑查询,然后查SHOW STATUS LIKE 'Handler_read%':Handler_read_rnd_next显著下降 +Handler_read_next上升,才是 MRR 生效的强证据 - 开启
SET optimizer_trace="enabled=on",执行后查information_schema.OPTIMIZER_TRACE,搜索"use_mrr": true和"mrr_cost"是否为非空值 -
read_rnd_buffer_size值太小会导致 MRR 提前刷出缓冲区,频繁分批回表——可临时调大(比如设为 4M)观察性能变化,但注意别超sort_buffer_size限制
MRR 的核心价值不在“多范围”,而在“按主键排序后批量回表”。最容易被忽略的是:它只对二级索引 + 非覆盖查询生效,且效果高度依赖数据物理分布和 buffer 容量。机械盘上提升明显,SSD 上可能感知不到,甚至因额外排序开销而略慢。


















