14.MySQL优化Block Nested-Loop and Batched Key Access Joins

介绍

在MySQL中,Batched Key Access (BKA) Join algorithm该算法用于对联接表和连接缓冲区的索引访问。BKA算法支持内连接,外连接和半连接操作,包括嵌套外连接。BKA的优点包括由于更高效的表扫描而提高了连接性能。此外,先前仅用于内连接的块嵌套循环(BNL)连接算法已扩展,可用于外连接和半连接操作,包括嵌套外连接。

以下部分讨论了连接缓冲区管理,它是原始BNL算法扩展,扩展BNL算法和BKA算法的基础。

  • Join Buffer Management for Block Nested-Loop and Batched Key Access Algorithms 加入块嵌套循环和批量密钥访问算法的缓冲区管理
  • Block Nested-Loop Algorithm for Outer Joins and Semi-Joins 用于外连接和半连接的块嵌套循环算法
  • Batched Key Access Joins 批量密钥访问连接
  • Optimizer Hints for Block Nested-Loop and Batched Key Access Algorithms 块嵌套循环和批量密钥访问算法的优化器提示

1 Join Buffer Management for Block Nested-Loop and Batched Key Access Algorithms

MySQL可以使用连接缓冲区不仅可以执行内部联接而无需对内部表进行索引访问,还可以执行子查询展平后出现的外部联接和半联接。此外,当存在对内部表的索引访问时,可以有效地使用连接缓冲区。

当存储感兴趣的行列的值时,连接缓冲区管理代码更有效地利用连接缓冲区:如果行的值为NULL,则不在缓冲区中为行列分配额外字节,并且对varchar类型的每一个值分配最小的字节。

他定义了两种类型的缓冲区:常规缓冲区和增量缓冲区。假设表t1与t2连接的时候使用连接缓冲区B1,然后他们的结果与表t3连接使用连接缓冲区B2:

  • 常规连接缓冲区包含来自每个连接操作数的列。如果B2是一个常规的连接缓冲区,放入B2中的每一行r由来自B1的行r1的列和来自表t3的匹配行r2的有趣列组成。
  • 增量连接缓冲区仅包含第二个连接操作数生成的表行中的列。也就是说,它是第一个操作数缓冲区中一行的增量。假如B2是一个增量缓冲区,它包含感兴趣的行r2和在B1缓冲区t1的一个link。

增量连接缓冲区始终相对于早期连接操作的连接缓冲区是增量的,因此第一个连接操作的缓冲区始终是常规缓冲区。在刚刚给出的实例中,缓冲B1 用来连接表t1和 t2必须是常规缓冲区。

增量缓冲区用于一个连接操作中包含被连接的表中的一行当中他感兴趣的列。有第一个连接产生的表中的匹配的行中它感兴趣的列进行扩充。增量缓冲区中的若干行可以引用同一行r,只要所有这些行都匹配行r,则该行r的列存储在先前的连接缓冲区中。

增量缓冲区可以减少从先前连接操作使用的缓冲区中复制列的频率。这节省了缓冲区空间,因为在一般情况下,第一个连接操作数产生的行可以由第二个连接操作数产生的几个行匹配。不必从第一个操作数生成一行的多个副本。由于复制时间的减少,增量缓冲区还可以节省处理时间。

系统变量 的block_nested_loop和 batched_key_access标志 optimizer_switch控制优化器如何使用块嵌套循环和批量密钥访问连接算法。

3 Block Nested-Loop Algorithm for Outer Joins and Semi-Joins

MySQL BNL算法的原始实现被扩展为支持外连接和半连接操作。

当使用连接缓冲区执行这些操作时,每个放入缓冲区的行都会提供一个匹配标志。

如果使用连接缓冲区执行外连接操作,则检查第二个操作数生成的表的每一行是否与连接缓冲区中的每一行匹配。找到匹配项后,将形成一个新的扩展行(原始行加上第二个操作数中的列),并通过其余的连接操作发送以进一步扩展。此外,启用缓冲区中匹配行的匹配标志。在检查了要连接的表的所有行之后,将扫描连接缓冲区。缓冲区中没有启用匹配标志的每一行都由NULL补充扩展(NULL 第二个操作数中每列的值),并由剩余的连接操作发送以进一步扩展。

系统变量 的block_nested_loop标志 optimizer_switch控制优化器如何使用块嵌套循环算法。

在EXPLAIN输出时,使用BNL时Extra中会包含Using join buffer (Block Nested Loop),type的值是ALL, index,或 range。

4 Batched Key Access Joins

MySQL实现了一种连接表的方法,叫做Batched Key Access(BKA),当存在对第二个连接操作数生成的表的索引访问时,可以应用BKA。像BNL算法一样,BKA算法采用连接缓冲区积累由连接操作产生的第一个的行中的感兴趣的列。然后BKA算法建立KEY到表的访问在缓冲区中连接所有行,,并将这些KEY批量提交到数据库引擎以进行索引查找。在提交key之后,MRR引擎函数以最佳方式在索引中执行查找,获取由这些密钥找到的连接表的行,并开始向匹配行提供BKA连接算法。每个匹配行与对连接缓冲区中的行的引用相耦合。

使用BKA时,值join_buffer_size定义了每个请求到存储引擎的批量密钥的大小。缓冲区越大,对连接操作的右侧表的顺序访问就越多,这可以显着提高性能。

要使用BKA,必须将系统变量的batched_key_access标志 optimizer_switch设置为on。BKA使用MRR,因此mrr标志也必须是 on。目前,MRR的成本估算过于悲观。因此,也有必要对 mrr_cost_based要 off用于要使用的BKA。以下设置启用BKA:

mysql> SET optimizer_switch='mrr=on,mrr_cost_based=off,batched_key_access=on';

MRR功能有两种执行方式:

  • 第一种方案用于传统的基于磁盘的存储引擎,例如InnoDB和 MyISAM。对于这些引擎,通常将来自连接缓冲区的所有行的键一次提交给MRR接口。特定于引擎的MRR函数对提交的密钥执行索引查找,从中获取行ID(或主键),然后根据BKA算法的请求逐个获取所有这些选定行ID的行。返回的每一行都带有一个关联引用,该引用允许访问连接缓冲区中的匹配行。MRR函数以最佳方式获取行:它们以行ID(主键)顺序获取。这提高了性能,因为读取是按磁盘顺序而不是随机顺序。
  • 第二种方案用于远程存储引擎,例如NDB。来自连接缓冲区的一部分行的密钥包及其关联由MySQL服务器(SQL节点)发送到MySQL Cluster数据节点。作为回报,SQL节点接收匹配行的包(或多个包)以及相应的关联。BKA连接算法获取这些行并构建新的连接行。然后将一组新密钥发送到数据节点,并使用返回的包中的行来构建新的连接行。该过程将继续,直到将来自联接缓冲区的最后一个密钥发送到数据节点,并且SQL节点已接收并加入与这些密钥匹配的所有行。

对于第一种情况,保留一部分连接缓冲区以存储由索引查找选择的行ID(主键),并作为参数传递给MRR功能。

没有特殊的缓冲区来存储为连接缓冲区中的行构建的密钥。相反,为缓冲区中的下一行构建键的函数作为参数传递给MRR函数。

在EXPLAIN输出中,使用BKA时Extra显示的值是Using join buffer (Batched Key Access),type的值是 ref或者eq_ref.

5 Optimizer Hints for Block Nested-Loop and Batched Key Access Algorithms

除了使用 optimizer_switch系统变量控制优化器在会话范围内使用BNL和BKA算法之外,MySQL还支持优化器提示以基于每个语句影响优化器。

猜你喜欢

转载自blog.csdn.net/ciqingloveless/article/details/83819042