8.2.1.10 多范围读取优化
当 table 较大且未存储在存储引擎的高速缓存中时,在辅助索引上使用范围扫描来读取行会导致对 table 的许多随机磁盘访问。通过磁盘扫描多范围读取(MRR)优化,MySQL 尝试通过首先仅扫描索引并收集相关行的键来减少用于范围扫描的随机磁盘访问次数。然后对键进行排序,最后使用主键的 Sequences 从基 table 中检索行。磁盘扫描 MRR 的动机是减少随机磁盘访问的次数,而是对基 table 数据进行更 Sequences 的扫描。
多范围读取优化具有以下优点:
-
MRR 使基于索引 Tuples 的数据行可以 Sequences 访问,而不是以随机 Sequences 访问。服务器获取一组满足查询条件的索引 Tuples,并根据数据行 IDSequences 对它们进行排序,然后使用排序后的 Tuples 按 Sequences 检索数据行。这使得数据访问更加高效且成本更低。
-
对于需要通过索引 Tuples 访问数据行的操作(例如范围索引扫描和使用索引作为联接属性的等联接),MRR 支持对键访问请求的批处理。 MRR 在一系列索引范围内进行迭代以获得合格的索引 Tuples。随着这些结果的累积,它们将用于访问相应的数据行。在开始读取数据行之前不必获取所有索引 Tuples。
在虚拟生成的列上创建的二级索引不支持 MRR 优化。 InnoDB
支持虚拟生成的列上的二级索引。
以下方案说明了 MRR 优化何时可以发挥优势:
方案 A:MRR 可用于InnoDB
和MyISAM
table,以进行索引范围扫描和等联接操作。
-
索引 Tuples 的一部分累积在缓冲区中。
-
缓冲区中的 Tuples 按其数据行 ID 排序。
-
根据排序的索引 Tuples 序列访问数据行。
方案 B:MRR 可用于NDBtable 以进行多范围索引扫描,或在通过属性执行均等联接时使用。
-
一部分范围(可能是单键范围)累积在提交查询的中心节点上的缓冲区中。
-
范围被发送到访问数据行的执行节点。
-
被访问的行被打包到程序包中并发送回中心节点。
-
收到的带有数据行的数据包将放置在缓冲区中。
-
从缓冲区读取数据行。
使用 MRR 时,EXPLAIN输出中的Extra
列显示Using MRR
。
如果不需要访问完整 table 行以产生查询结果,则InnoDB
和MyISAM
不使用 MRR。如果可以完全基于索引 Tuples 中的信息(通过covering index)产生结果,则为这种情况; MRR 没有任何好处。
两个optimizer_switch系统变量标志提供了使用 MRR 优化的接口。 mrr
标志控制是否启用 MRR。如果启用了mrr
(on
),则mrr_cost_based
标志控制优化器是尝试在使用还是不使用 MRR(on
)之间做出基于成本的选择,还是在可能的情况下(off
)使用 MRR。默认情况下,mrr
是on
,mrr_cost_based
是on
。参见第 8.9.2 节“可切换的优化”。
对于 MRR,存储引擎使用read_rnd_buffer_size系统变量的值作为可为其缓冲区分配多少内存的准则。引擎最多使用read_rnd_buffer_size个字节,并确定一次处理要处理的范围数。