使用辅助索引上的范围扫描读取行会导致许多随机磁盘访问基本表,尤其是在表很大且未存储在存储引擎的缓存中时。通过磁盘扫描多范围读取 (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
字节,并确定在一次遍历中要处理的范围数量。