bigywater.tech
MySQL / InnoDB · 35

MRR 多范围读取

用EXPLAIN FORMAT=JSON确认MRR生效后,用计时验证在本机NVMe SSD上MRR是否真的带来了预期的性能提升。

multi_range_read:true
确认MRR被启用
未提速
多次重复测试没有观察到性能优势
SSD vs 机械硬盘
MRR收益取决于存储介质

做的事:一张50万行的表,验证MRR是否被启用

MRR的设计初衷是把范围扫描里零散的行查找排序,换成更顺序的磁盘访问。

建表插入CREATE TABLE t17 (id INT PRIMARY KEY AUTO_INCREMENT, k INT, payload VARCHAR(200), INDEX idx_k(k)); 插入50万行,k随机1~100000 SET SESSION optimizer_switch='mrr=on,mrr_cost_based=off';

验证:EXPLAIN FORMAT=JSON确认MRR生效了

普通EXPLAIN文本看不出来,要用JSON格式才能确认。

结果EXPLAIN FORMAT=JSON SELECT * FROM t17 WHERE k BETWEEN 1000 AND 3000 "operation": "Index range scan (Multi-Range Read) on t17 using idx_k ..." "multi_range_read": true

确认了:把 mrr_cost_based 关掉、强制 mrr=on 之后,这次范围扫描用上了MRR——操作文本里明确写着"(Multi-Range Read)",JSON里 multi_range_read 字段是true。

意外发现:测出的耗时,MRR反而没有更快

按理论,MRR应该通过排序访问顺序减少随机I/O。

结果(3次重复)mrr=on,mrr_cost_based=off: 0.0629s / 0.0287s / 0.0266s mrr=off: 0.0293s / 0.0264s / 0.0263s (mrr=off每次都不比mrr=on慢,甚至经常更快)

测出的结果跟理论预期相反:开启MRR并没有带来速度提升,多次重复测试里 mrr=off 始终跟 mrr=on 持平或更快,从未出现明显的性能优势。

原因跟本机的硬件环境有关:MRR解决的问题是"按索引顺序去查主键行,会在磁盘上东跳西跳"——这在机械硬盘上代价很高(每次跳转都有的寻道延迟),MRR把这些零散的行查找按主键顺序重新排列,能换来更顺序的磁盘访问。但本机跑在NVMe SSD上,随机访问和顺序访问的延迟差距本身就很小,MRR为了排序这批待查找的行而付出的额外开销(构建、排序缓冲区),在这种硬件上反而可能得不偿失。这是一个的、诚实的反直觉结论:MRR是否带来收益,取决于底层存储介质的随机访问代价,不能脱离硬件环境断言"开了肯定更快"。

分步演示:MRR生效但没提速的过程

每一步都是本文上面用EXPLAIN和计时跑出来的原始结果。

MRR生效了,但在本机SSD上没有带来预期收益
这一步新验证的结果

    本文用到的工具

    • 本机 MySQL 26.7.0(InnoDB),50万行表,NVMe SSD存储
    • EXPLAIN FORMAT=JSON / optimizer_switch mrr:验证MRR生效与性能
    京ICP备2026067502号-1京公网安备11010502063487号