MySQL8 的 Hash join 算法

以前 MySQL 的 join 算法只有 nested loop 这一种,在 MySQL8 中推出了一种新的算法 hash join,比 nested loop 更加高效。

下面我就看看它是怎么工作的。

用这个SQL作为例子:

hash join 工作过程分为2个阶段:

  • build 构建阶段
  • probe 探测阶段

1. 构建阶段

从参与join的2个表中选一个,选择占空间小的那个表,不是行数少的,这里假设选择了 countries 表。

countries 表中每行的 join 字段值进行 hash 计算:

hash(countries.country_id)

计算后放入内存中 hash table 的相应位置。

所有行都存放到 hash table 之后,构建阶段完成。

2. 探测阶段

persons 表中每行中的 join 字段的值进行 hash 计算:

hash(persons.country_id)

拿着计算结果到内存 hash table 中进行查找匹配,找到一行就发给 client。

这样就完成了整个 join 操作,每个表只扫描一次就可以了,扫描匹配时间也是恒定的,非常高效。

这个例子中,countries 表顺利的全部放入了内存,可用内存的大小是由 join_buffer_size 控制的。

实际环境中,肯定会有比较大的表,那么超过了可用内存时怎么办呢?

需要溢出到磁盘了。

3. 溢出到磁盘

在构建阶段过程中,如果内存满了,会把表中剩余数据写到磁盘上。

不会只写入一个文件,会分成多个块文件。

MySQL 会保证每个块文件的大小都是适合可用内存的。

怎么决定某一行记录写入哪个块文件呢?也是通过hash计算join字段决定的:

hash_2(countries.country_id)

可以看到,对于大表,构建阶段分为了2步:

  • 写入内存 hash table
  • 写入块文件

然后是探测阶段,首先还是会走一遍和之前一样的流程,就是扫描一遍 persons 表的每一行,和内存中的 hash table 进行匹配。

但因为内存中的 hash table 不是全部数据,所以需要额外的处理:

persons 表的数据也写入多个块文件中。

怎么决定某一行记录写入哪个块文件呢?和构建阶段写入块文件的思路相同,这样,构建阶段的块文件和此处的块文件就是一一对应的关系了。

在正常的探测流程走完之后,开始处理这些块文件中的内容了。

逐一加载构建阶段的块文件到内存中,加载过程和正常的构建过程一致,对块文件中的每行数据进行 hash 计算,放入内存的 hash table 中。

构建好一个块文件之后,选择与其对应的探测块文件开始探测。

例如构建的是第0个构建块文件,那么就选择第0个探测块文件。

就这样一对一对的块文件进行处理,直到全部完成。

小结

hash join 算法先选一个小表,放入内存的 hash table,然后扫描另一个表,与 hash table 匹配出结果数据。

当表太大,无法一次放入内存时,就分而治之,写入块文件,再对每个块文件走一遍正常时的流程。

参考资料:

https://mysqlserverteam.com/hash-join-in-mysql-8/

来源:公众号 “性能与架构”

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL中的哈希连接(hash join)是一种连接算法,用于将两个表的数据进行连接操作。它使用哈希表作为中间数据结构,在内存中构建一个哈希表,然后根据哈希值将相同键值的行连接起来。 当执行一个哈希连接时,MySQL会选择一个较小的表作为驱动表(也称为外部表),并将其加载到内存中的哈希表中。然后它会扫描另一个较大的表(也称为内部表),并将每一行的键值与哈希表中的键值进行比较。如果存在匹配的键值,则将两个表中的相应行进行连接。 哈希连接适用于以下场景: 1. 连接的两个表中,其中一个表非常小,可以完全加载到内存中。 2. 连接的两个表没有适合使用索引进行连接的列。 要使用哈希连接,可以在查询中使用JOIN关键字,并指定连接类型为HASH。例如: ``` SELECT * FROM table1 JOIN table2 HASH (join_column) ON table1.join_column = table2.join_column; ``` 在执行哈希连接时,MySQL会自动选择使用哈希连接算法还是其他连接算法,如嵌套循环连接(nested loop join)或排序合并连接(sort merge join),具体取决于查询的复杂性、表大小和可用内存等因素。 需要注意的是,哈希连接可能需要较大的内存空间来构建哈希表,因此在使用哈希连接时要确保系统具有足够的内存资源。此外,哈希连接在某些情况下可能会导致性能下降,因此在实际使用中要根据具体情况进行评估和调优。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值