mysql 5.7中的MBR和BKA算法

一、什么是MRR
MMR全称是Multi-Range Read,是MYSQL5.6优化器的一个新特性,在MariaDB5.5也有这个特性。优化的功能在使用二级索引做范围扫描的过程中减少磁盘随机IO和减少主键索引的访问次数。将随机IO转换为顺序IO

二、MRR和没有MRR的区别

给出一个简单的例子,在innodb表执行下面的查询:

SELECT non_key_column FROM tbl WHERE key_column=x
在没有MRR的情况下,它是这样得到结果的:

1. select key_column, pk_column from tb where key_column=x order by key_column ---> 假设这个结果集是t
2. for each row in t ; select non_key_column from tb where pk_column = pk_column_value。(在oracle里第2步叫回表)
在有MRR的情况下,它是这样执行的:
1. select key_column, pk_column from tb where key_column = x order by key_column ---> 假设这个结果集是t
2. 将结果集t放在buffer里面(直到buffer满了),然后对结果集t按照pk_column排序 ---> 假设排序好的结果集是t_sort
3. select non_key_column fromtb where pk_column in (select pk_column from t_sort)
两者的区别主要是两点:

1. 没有MRR的情况下,随机IO增加,因为从二级索引里面得到的索引元组是有序,但是他们在主键索引里面却是无序的,所以每次去主键索引里面得到non_key_column的时候都是随机IO。(如果索引覆盖,那也就没必要利用MRR的特性了,直接从索引里面得到所有数据)

2. 没有MRR的情况下,访问主键索引的次数增加。没有MRR的情况下,二级索引里面得到多少行,那么就要去访问多少次主键索引(也不能完全这样说,因为mysql实现了BNL),而有了MRR的时候,次数就大约减少为之前次数t/buffer_size。


二 BKA
Batched Key Access (BKA) 提高表join性能的算法。当被join的表能够使用索引时,就先排好顺序,然后再去检索被join的表,听起来和MRR类似,实际上MRR也可以想象成二级索引和 primary key的join
如果被Join的表上没有索引,则使用老版本的BNL策略(BLOCK Nested-loop)
BKA原理

对于多表join语句,当MySQL使用索引访问第二个join表的时候,使用一个join buffer来收集第一个操作对象生成的相关列值。BKA构建好key后,批量传给引擎层做索引查找。key是通过MRR接口提交给引擎的(mrr目的是较为顺序)MRR使得查询更有效率。

大致的过程如下:


BKA使用join buffer保存由join的第一个操作产生的符合条件的数据
然后BKA算法构建key来访问被连接的表,并批量使用MRR接口提交keys到数据库存储引擎去查找查找。
提交keys之后,MRR使用最佳的方式来获取行并反馈给BKA
BNL和BKA都是批量的提交一部分行给被join的表,从而减少访问的次数,那么它们有什么区别呢?


BNL比BKA出现的早,BKA直到5.6才出现,而NBL至少在5.1里面就存在。
BNL主要用于当被join的表上无索引
BKA主要是指在被join表上有索引可以利用,那么就在行提交给被join的表之前,对这些行按照索引字段进行排序,因此减少了随机IO,排序这才是两者最大的区别,但是如果被join的表没用索引呢?那就使用NBL
BKA和BNL标识

Using join buffer (Batched Key Access)和Using join buffer (Block Nested Loop)
相关参数

BAK使用了MRR,要想使用BAK必须打开MRR功能,而MRR基于mrr_cost_based的成本估算并不能保证总是使用MRR,官方推荐设置mrr_cost_based=off来总是开启MRR功能。打开BAK功能(BAK默认OFF):
SET optimizer_switch='mrr=on,mrr_cost_based=off,batched_key_access=on';
复制代码
BKA使用join buffer size来确定buffer的大小,buffer越大,访问被join的表/内部表就越顺序。

BNL默认是开启的,设置BNL相关参数:
SET optimizer_switch=’block_nested_loop’
复制代码
支持inner join, outer join, semi-join operations,including nested outer joins
BKA主要适用于join的表上有索引可利用,无索引只能使用BNL


三 设置
SET global optimizer_switch='mrr=on,mrr_cost_based=off,batched_key_access=on';

你可能感兴趣的:(MySQL)