MySQL Hash Join前世今生
- GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
- GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。
- 作者:nw
MySQL Hash Join前世今生
因工作需要,对MySQL Hash Join的内部实现做了一些探索和实践,对这个由8.0.18开始引入的连接算法有了一定的了解,写文总结与各位大佬分享,欢迎大家指教。因篇幅较长,这份总结分成若干部分,我们今天先一起来看一下MySQL Hash join的变迁史。
爬了一下 MySQL worklog[1]
,并结合源码及各版本的实际使用,个人认为比较重要的worklogs为如下几个, 其它的变更一般围绕这些worklogs做的小调整或bugfixes,这里我们就不一一列举。
1. WL#2241: Hash join (变更版本:8.0.18)
主要内容:
- 新增执行类HashJoinIterator,实现hash join算法原型 (支持on-disk hash)
- HASH JOIN 仅支持INNER JOIN,并对使用hash join做了限制:关联表连接条件必须至少包含一条等值条件(equi-join condition, 如
t1.a = t2.a
),且join条件中的列不包含索引
注:这里我认为官网的 Release Notes[2]
描述是不太准确的,以如下例子为例,虽然该查询包含了非等值连接条件(non-equi-join condition, 如 t1.a <> t2.a
,t1.a = 1
, t2.a > 1
等),但实际查询中还是使用hash join的, 因为查询语句在解析执行过程中,可能会经历语句重写、sql优化等步骤,与表象上会有所不同,建议借助explain工具,查看实际上查询语句选择的join算法。
-- 版本:8.0.18
-- 在创建iterator时,t1.a > 1 会被当成表的过滤条件,而非inner join的join条件
-- 此查询仍使用了hash join(join 条件为空)
EXPLAIN FORMAT=tree SELECT * FROM t1 JOIN t2 ON t1.i > 1;
-> Inner hash join (cost=1.17 rows=3)
-> Table scan on t2 (cost=0.34 rows=2)
-> Hash
-> Filter: (t1.i > 1) (cost=0.65 rows=1)
-> Table scan on t1 (cost=0.65 rows=4)