本文主要翻译自 MySQL官方文档对MRR的介绍 。
当表的数据非常多以至于无法放入缓存时,基于二级索引的范围扫描读取数据会造成较多的硬盘随机读。如果启用了MRR优化,MySQL首先会基于索引进行数据定位并收集满足条件的keys,然后再对这些keys进行排序,这样可以以主键的顺序进行表行的读取,能够减少随机读的数量。MRR优化的目的就是通过对keys排序后的一定程度的顺序读减少随机读的数量。
MRR的优点如下:
下面列出的场景能够证明MRR优化的优点:
场景A,在 InnoDB 和 MyISAM 基于索引范围访问和 equi-join *** 作时,MRR优化可以发挥作用:
场景B,MRR可以在 NDB 基于 multiple-range index 扫描和 equi-join 是发挥作用:
使用MRR时, EXPLAIN 输出的 Extra 列会显示 Using MRR 。
当不需要进行全表访问时(full table), InnoDB 和 MyISAM 不会进行MRR优化,因为如果查询结果可以基于索引得出(比如覆盖索引),那么使用MRR将没有意义。
系统变量 optimizer_switch 使用标识 mrr 控制是否启用MRR优化,如果配置启用MRR优化,标识 mrr_cost_based 用来决定是否基于代价来决定是否进行MRR优化。默认情况下,MRR为启用状态,并且 mrr_cost_based 也是启用状态。
启用MRR优化时, read_rnd_buffer_size 用于控制分配多大空间积累批量访问表行数据的索引数据。
MRR 是 MySQL 针对特定查询的一种优化手段。假设一个查询有二级索引可用,读完二级索引后要回表才能查到那些不在当前二级索引上的列值,由于二级索引上引用的主键值不一定是有序的,因此就有可能造成大量的随机 IO,如果回表前把主键值给它排一下序,那么在回表的时候就可以用顺序 IO 取代原本的随机 IO。如果想关闭 MRR 优化的话,就要把优化器开关 mrr 设置为 off。
默认只有在优化器认为 MRR 可以带来优化的情况下才会走 MRR,如果你想不管什么时候能走 MRR 的都走 MRR 的话,你要把 mrr_cost_based 设置为 off,不过最好不要这么干,因为这确实是一个坑,MRR 不一定什么时候都好,全表扫描有时候会更加快,如果在这种场景下走 MRR 就完成了。
MRR 要把主键排个序,这样之后对磁盘的 *** 作就是由顺序读代替之前的随机读。从资源的使用情况上来看就是让 CPU 和内存多做点事,来换磁盘的顺序读。然而排序是需要内存的,这块内存的大小就由参数 read_rnd_buffer_size 来控制。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)