Multi-Range Read优化
1 概述
MySQL Multi-Range Read(MRR)优化主要用于在使用二级索引访问数据时减少随机读。
本文主要翻译自MySQL官方文档对MRR的介绍。
当表的数据非常多以至于无法放入缓存时,基于二级索引的范围扫描读取数据会造成较多的硬盘随机读。如果启用了MRR优化,MySQL首先会基于索引进行数据定位并收集满足条件的keys,然后再对这些keys进行排序,这样可以以主键的顺序进行表行的读取,能够减少随机读的数量。MRR优化的目的就是通过对keys排序后的一定程度的顺序读减少随机读的数量。
2 MRR的优点
MRR的优点如下:
-
MRR通过对索引得到的data row ID进行排序,在一定程度上以主键的顺序访问数据,能够减少随机读的次数。
-
MRR会基于索引扫描的结果收集访问表行的keys,批量访问数据行,通过这种批量访问在找到满足数量的索引数据之后会停止索引数据的读取,然后使用收集的keys批量读取表行在一定程度上也避免了多索引数据的过多访问。
下面列出的场景能够证明MRR优化的优点:
场景A,在InnoDB
和MyISAM
基于索引范围访问和equi-join
操作时,MRR优化可以发挥作用:
- 部分索引数据会在缓冲中被收集起来;
- 对这些收集起来的索引数据中的data row ID(主键)进行排序;
- 根据排序之后的主键对表行数据进行访问。
场景B,MRR可以在NDB
基于multiple-range index
扫描和equi-join
是发挥作用:
- 当查询提交时,部分索引数据会在central节点被收集;
- 这部分索引数据会被发送给execution节点进行表行访问;
- 读取的表行数据会作为响应发送给central节点;
- central节点将接收到返回的表行数据放入缓冲中;
- central节点从缓冲中读取表行数据。
使用MRR时,EXPLAIN
输出的Extra
列会显示Using MRR
。
3 使用限制和配置
当不需要进行全表访问时(full table),InnoDB
和MyISAM
不会进行MRR优化,因为如果查询结果可以基于索引得出(比如覆盖索引),那么使用MRR将没有意义。
系统变量optimizer_switch
使用标识mrr
控制是否启用MRR优化,如果配置启用MRR优化,标识mrr_cost_based
用来决定是否基于代价来决定是否进行MRR优化。默认情况下,MRR为启用状态,并且mrr_cost_based
也是启用状态。
启用MRR优化时,read_rnd_buffer_size
用于控制分配多大空间积累批量访问表行数据的索引数据。