这几天看到mrr的东西,恰好看到之前咱们组的一个小伙的博客,我看挺全的,就转过来了,原博客地址请戳css
一 介绍
MySQL 5.6版本提供了不少性能优化的特性,其中之一就是 Multi-Range Read 多范围读(MRR) , 它的做用针对基于辅助/第二索引的查询,减小随机IO,而且将随机IO转化为顺序IO,提升查询效率。
二 原理
在没有MRR以前,或者没有开启MRR特性时,MySQL 针对基于辅助索引的查询策略是这样的:html
- select non_key_column from tb wherekey_column=x;
MySQL 执行查询的伪代码mysql
- 第一步 先根据where条件中的辅助索引获取辅助索引与主键的集合,结果集为rest。
- select key_column, pk_column from tb where key_column=x order by key_column
- 第二步 经过第一步获取的主键来获取对应的值。
- for each pk_column value in rest do:
- select non_key_column from tb where pk_column=val

因为MySQL存储数据的方式: 辅助索引的存储顺序并不是与主键的顺序一致,从图中能够看出,根据辅助索引获取的主键来访问表中的数据会致使随机的IO . 不一样主键不在同一个page 里面时必然致使屡次IO 和随机读。
在使用MRR优化特性的状况下,MySQL 针对基于辅助索引的查询策略是这样的:sql
- 第一步 先根据where条件中的辅助索引获取辅助索引与主键的集合,结果集为rest
- select key_column, pk_column from tb where key_column = x order by key_column
- 第二步 将结果集rest放在buffer里面(read_rnd_buffer_size 大小直到buffer满了),而后对结果集rest按照pk_column排序,获得结果集是rest_sort
- 第三步 利用已经排序过的结果集,访问表中的数据,此时是顺序IO.
- select non_key_column fromtb where pk_column in ( rest_sort )

从图示MRR原理,MySQL 将根据辅助索引获取的结果集根据主键进行排序,将乱序化为有序,能够用主键顺序访问基表,将随机读转化为顺序读,多页数据记录可一次性读入或根据这次的主键范围分次读入,以减小IO操做,提升查询效率。
三 相关参数
咱们能够经过参数 optimizer_switch 的标记来控制是否使用MRR,当设置mrr=on时,表示启用MRR优化。mrr_cost_based 表示是否经过 cost base的方式来启用MRR.若是选择mrr=on,mrr_cost_based=off,则表示老是开启MRR优化。
参数read_rnd_buffer_size 用来控制键值缓冲区的大小。
四 案例介绍
当开启MRR时
性能优化
- MySQL > explain select * from tbl where tbl.key1 between 1000 and 2000;
- +----+-------------+-------+-------+---------------+------+---------+------+------+-------------------------------------------+
- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
- +----+-------------+-------+-------+---------------+------+---------+------+------+-------------------------------------------+
- | 1 | SIMPLE | tbl | range | key1 | key1 | 5 | NULL | 960 | Using index condition; Using MRR |
- +----+-------------+-------+-------+---------------+------+---------+------+------+-------------------------------------------+
- 1 row in set (0.03 sec)
五 MRR的使用限
MRR 适用于如下两种状况。
1 range access
2 ref and eq_ref access, when they are using Batched Key Access
六 参考文章
《MariaDB Multi-Range Read Optimization》
《MySQL Multi-Range Read Optimization》
《Multi Range Read (MRR) in MySQL 5.6 and MariaDB 5.5》 性能