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