本篇我们来看下 calcite 中 join 实现和相关优化规则。接下来我们将从下往上, 首先看下 join 支持的实现算法,之后看下优化器如何选择使用这些 join 算法,最后看几个经典的 join 优化规则(join reorder and so on...)
支持的 Join 执行器
在之前简述 implement文章中我们看到 calcite 的算子实现会 codegen 调用 linq4j 提供的 enumerable 算子实现, 今天我们看下 join 相关的处理。
calcite 使用了 linq4j 的 5 种 join 方法
- join(hash join)
- mergeJoin
- semiJoin
- thetaJoin
- correlateJoin
(linq4j 还提供了 groupJoin 不过 calcite 暂时没用)
这些算法的实现位于 EnumerableDefaults, 并通过 Enumerable.*Join 中的 implement 来生成对应方法的调用,如果希望寻找对应调用的地方可以查找 BuiltInMethod 中对应的值使用的地方即可。
1) Join(equi hash)
这个 join 主要支持等值比较条件的 join,通过 hashjoin 实现, 代码位于 join_ 方法内, linq4j 这个方法的实现是首先对 inner 表(join 的第二个 enumerable) 构造 lookup(hashMap<k, list<v>>
), 之后通过在 Enumerable#moveNext 实现中, move outer 表并去 probe 刚才构建的内表 lookup, 并合并选择返回结果>
整个过程很简单没实现啥并行 hashjoin 等稍复杂的算法, 但可能需要稍微关注的是几个参数: generateNullsOnLeft
(right/full join) 会留一份 inner 的 map key, 最后将未匹配的行对左边补 null; generateNullsOnRight
(left/full join) 反之对右边补充 null, 不过只用简单发现 prob 不到就补 null
这个 hashjoin 算法会作为 EnumerableJoin 的 implement 实现(根据 join type 等生成其他参数), 所以优化器要选择 hashjoin 需要转换好 EnumerableJoin 并安排好 left/right 即可。
2) Merge Join
<