当基表很大且没有存储在存储引擎的缓存中时,在辅助索引上使用范围扫描读取行可能会导致对基表的多次随机磁盘访问。使用磁盘扫描多范围读取(MRR)优化,MySQL尝试通过首先只扫描索引并收集相关行的键来减少范围扫描的随机磁盘访问数量。然后对键进行排序,最后使用主键的顺序从基表中检索行。磁盘扫描MRR的动机是减少随机磁盘访问的数量,而是实现对基本表数据的更有序的扫描。
多范围读取优化提供了以下好处:
MRR允许根据索引元组按顺序访问数据行,而不是按随机顺序。服务器获取一组满足查询条件的索引元组,按照数据行ID的顺序进行排序,然后使用排序后的元组按顺序检索数据行。这使得数据访问更高效,成本更低。
MRR支持批处理要求通过索引元组访问数据行的操作的键访问请求,例如范围索引扫描和为join属性使用索引的等连接。MRR迭代索引范围序列以获得符合条件的索引元组。随着这些结果的积累,它们将用于访问相应的数据行。在开始读取数据行之前,没有必要获取所有索引元组。
在虚拟生成的列上创建二级索引不支持MRR优化。InnoDB
支持虚拟生成列上的二级索引。
以下场景说明了MRR优化的优势:
场景A: MRR可用于InnoDB
而且MyISAM
索引范围扫描和等连接操作的表。
索引元组的一部分被累积在缓冲区中。
缓冲区中的元组按数据行ID排序。
根据已排序的索引元组序列访问数据行。
场景B: MRR可用于NDB
表用于多范围索引扫描或通过属性执行相等连接。
一部分范围(可能是单键范围)被累积在提交查询的中心节点上的缓冲区中。
范围被发送到访问数据行的执行节点。
被访问的行被打包到包中并发送回中心节点。
接收到的带有数据行的包被放置在缓冲区中。
从缓冲区中读取数据行。
当使用MRR时,额外的
列解释
输出显示使用MRR
.
InnoDB
而且MyISAM
如果不需要访问完整的表行来产生查询结果,则不使用MRR。如果结果可以完全基于索引元组中的信息(通过覆盖索引);MRR没有任何好处。
两个optimizer_switch
系统变量标志提供了使用MRR优化的接口。的mrr
flag控制是否启用MRR。如果mrr
已启用(在
),mrr_cost_based
标志控制优化器是否试图在使用和不使用MRR之间做出基于成本的选择(在
)或尽可能使用MRR (从
).默认情况下,mrr
是在
而且mrr_cost_based
是在
.看到第8.9.2节,“可切换优化”.
对于MRR,存储引擎使用的值read_rnd_buffer_size
系统变量作为它可以为缓冲区分配多少内存的指导方针。发动机的耗电量达到read_rnd_buffer_size
字节,并确定在一次传递中要处理的范围的数量。