> For the complete documentation index, see [llms.txt](https://yanghaiji.gitbook.io/advanced-books/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yanghaiji.gitbook.io/advanced-books/note/mysql/book/sql-you-hua-9/duo-fan-wei-du-qu-you-hua.md).

# 4.9多范围读取优化

当表较大且未存储在存储引擎的高速缓存中时，在辅助索引上使用范围扫描来读取行可能导致对表的许多随机磁盘访问。通过磁盘扫描多范围读取（MRR）优化，MySQL尝试通过首先仅扫描索引并收集相关行的键来减少用于范围扫描的随机磁盘访问次数。然后对键进行排序，最后使用主键的顺序从基表中检索行。磁盘扫描MRR的动机是减少随机磁盘访问的次数，而是对基表数据进行更顺序的扫描。

多范围读取优化具有以下优点：

* MRR使基于索引元组的数据行可以顺序访问，而不是以随机顺序访问。服务器获取一组满足查询条件的索引元组，并根据数据行ID顺序对它们进行排序，然后使用排序后的元组按顺序检索数据行。这使得数据访问更加高效且成本更低。
* 对于需要通过索引元组访问数据行的操作（例如范围索引扫描和使用索引作为联接属性的等联接）的操作，MRR支持对键访问请求的批处理。MRR在一系列索引范围内进行迭代以获得合格的索引元组。随着这些结果的累积，它们将用于访问相应的数据行。在开始读取数据行之前不必获取所有索引元组。

在虚拟生成的列上创建的二级索引不支持MRR优化。 `InnoDB`支持虚拟生成的列上的二级索引。

以下方案说明了MRR优化何时可以发挥优势：

方案A：MRR可用于`InnoDB`和 `MyISAM`表，用于索引范围扫描和等联接操作。

1. 索引元组的一部分累积在缓冲区中。
2. 缓冲区中的元组按其数据行ID排序。
3. 根据排序的索引元组序列访问数据行。

方案B：MRR可用于 `NDB`表以进行多范围索引扫描，或在按属性执行等值联接时使用。

1. 一部分范围（可能是单键范围）累积在提交查询的中心节点上的缓冲区中。
2. 范围被发送到访问数据行的执行节点。
3. 被访问的行被打包到程序包中并发送回中心节点。
4. 收到的带有数据行的数据包将放置在缓冲区中。
5. 从缓冲区读取数据行。 使用MRR时Extra，EXPLAIN输出中的列 显示 Using MRR。

InnoDBMyISAM如果不需要访问整个表行以产生查询结果，则不要使用MRR。如果可以完全根据索引元组中的信息（通过覆盖索引）产生结果，则为这种情况；MRR没有任何好处。

两个optimizer\_switch系统变量标志提供了使用MRR优化的接口。该mrr标志控制是否启用MRR。如果mrr启用（on），则该mrr\_cost\_based 标志控制优化器是尝试在使用MRR与不使用MRR之间做出基于成本的选择（on）还是在可能的情况下使用MRR（off）。默认情况下，mrr is on和mrr\_cost\_based is on。

对于MRR，存储引擎将read\_rnd\_buffer\_size系统变量的值 用作可为其缓冲区分配多少内存的准则。引擎最多使用 read\_rnd\_buffer\_size字节，并确定一次处理要处理的范围数。
