dataalive commented on code in PR #9753: URL: https://github.com/apache/incubator-doris/pull/9753#discussion_r880515874
########## docs/zh-CN/advanced/join-optimization/doris-join-optimization.md: ########## @@ -0,0 +1,226 @@ +--- +{ + "title": "Doris Join 优化原理", + "language": "zh-CN" +} + + +--- + +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> + +# Doris Join 优化原理 + +Doris 支持两种物理算子,一类是 **Hash Join**,另一类是 **Nest Loop Join**。 + +- Hash Join:在右表上根据等值 Join 列建立哈希表,左表流式的利用哈希表进行 Join 计算,它的限制是只能适用于等值 Join。 +- Nest Loop Join:通过两个 for 循环,很直观。然后它适用的场景就是不等值的 Join,例如:大于小于或者是需要求笛卡尔积的场景。它是一个通用的 Join 算子,但是性能表现差。 + +作为分布式的 MPP 数据库, 在 Join 的过程中是需要进行数据的 Shuffle。数据需要进行拆分调度,才能保证最终的 Join 结果是正确的。举个简单的例子,假设关系S 和 R 进行Join,N 表示参与 Join 计算的节点的数量;T 则表示关系的 Tuple 数目。 + + + +## Doris Shuffle 方式 + +Doris 支持 4 种 Shuffle 方式 + +1. BroadCast Join + + 它要求把右表全量的数据都发送到左表上,即每一个参与 Join 的节点,它都拥有右表全量的数据,也就是 T(R)。 + + 它适用的场景是比较通用的,同时能够支持 Hash Join 和 Nest loop Join,它的网络开销 N * T(R)。 + +  + + 左表数据不移动,右表数据发送到左表数据的扫描节点。 + +2. Shuffle Join + + 当进行 Hash Join 时候,可以通过 Join 列计算对应的 Hash 值,并进行 Hash 分桶。 + + 它的网络开销则是:T(R) + T(N),但它只能支持 Hash Join,因为它是根据 Join 的条件也去做计算分桶的。 + +  + + 左右表数据根据分区,计算的记过发送到不同的分区节点上。 + +3. Bucket Shuffle Join + + Doris 的表数据本身是通过 Hash 计算分桶的,所以就可以利用表本身的分桶列的性质来进行 Join 数据的 Shuffle。假如两张表需要做 Join,并且 Join 列是左表的分桶列,那么左表的数据其实可以不用去移动右表通过左表的数据分桶发送数据就可以完成 Join 的计算。 + + 它的网络开销则是:T(R)相当于只 Shuffle 右表的数据就可以了。 + +  + + 左表数据不移动,右表数据根据分区计算的结果发送到左表扫表的节点 + +4. Colocation + + 它与 Bucket Shuffle Join 相似,相当于在数据导入的时候,根据预设的 Join 列的场景已经做好了数据的 Shuffle。那么实际查询的时候就可以直接进行 Join 计算而不需要考虑数据的 Shuffle 问题了。 + +  + + 数据已经预先分区,直接在本地进行 Join 计算 + +### 四种 Shuffle 方式对比 + +| Shuffle方式 | 网络开销 | 物理算子 | 适用场景 | +| -------------- | ----------- | -------------------------- | ------------------------------------------------------------ | +| BroadCast | N * T(R) | Hash Join / Nest Loop Join | 通用 | +| Shuffle | T(S) + T(R) | Hash Join | 通用 | +| Bucket Shuffle | T(R) | Hash Join | Join条件中存在左表的分布式列,且左表执行时为单分区 | +| Colocate | 0 | Hash Join | Join条件中存在左表的分布式列,切左右表同属于一个Colocate Group | + +N : 参与 Join 计算的 Instance 个数 + +T(关系) : 关系的 Tuple 数目 + +上面这 4 种方式灵活度是从高到低的,它对这个数据分布的要求是越来越严格,但 Join 计算的性能也是越来越好的。 + +## Runtime Filter Join 优化 + +Doris 在进行 Hash Join 计算时会在右表构建一个哈希表,左表流式的通过右表的哈希表从而得出 Join 结果。而 RuntimeFilter 就是充分利用了右表的 Hash 表,在右表生成哈希表的时,同时生成一个基于哈希表数据的一个过滤条件,然后下推到左表的数据扫描节点。通过这样的方式,Doris 可以在运行时进行数据过滤。 + +假如左表是一张大表,右表是一张小表,那么利用左表生成的过滤条件就可以把绝大多数在 Join 层要过滤的数据在数据读取时就提前过滤,这样就能大幅度的提升 Join 查询的性能。 + +当前 Doris 支持三种类型 RuntimeFilter + +- 一种是 IN— IN,很好理解,将一个 hashset 下推到数据扫描节点。 +- 第二种就是 BloomFilter,就是利用哈希表的数据构造一个 BloomFilter,然后把这个 BloomFilter 下推到查询数据的扫描节点。。 +- 最后一种就是 MinMax,就是个 Range 范围,通过右表数据确定 Range 范围之后,下推给数据扫描节点。 + +Runtime Filter 适用的场景有两个要求: + +- 第一个要求就是右表大左表小,因为构建 Runtime Filter是需要承担计算成本的,包括一些内存的开销。 +- 第二个要求就是左右表 Join 出来的结果很少,说明这个 Join 可以过滤掉左表的绝大部分数据。 + +当符合上面两个条件的情况下,开启 Runtime Filter 就能收获比较好的效果 + +当 Join 列为左表的 Key 列时,RuntimeFilter 会下推到存储引擎。Doris 本身支持延迟物化, + +延迟物化简单来说是这样的:假如需要扫描 A、B、C 三列,在 A 列上有一个过滤条件: A 等于 2,要扫描 100 行的话,可以先把 A 列的 100 行扫描出来,再通过 A = 2 这个过滤条件过滤。之后通过过滤完成后的结果,再去读取 B、C 列,这样就能极大的降低数据的读取 IO。所以说 Runtime Filter 如果在 Key 列上生成,同时利用 Doris 本身的延迟物化来进一步提升查询的性能。 + +### Runtime Filter 类型 + +Doris 提供了三种不同的 Runtime Filter 类型: + +- **IN** 的优点就是效果过滤效果明显,且快速。它的缺点首先第一个它只适用于 BroadCast,第二,它右表超过一定数据量的时候就失效了,当前 Doris 目前配置的是1024,即右表如果大于 1024,IN 的 Runtime Filter 就直接失效了。 +- **MinMax** 的优点是开销比较小。它的缺点就是对数值列还有比较好的效果,但对于非数值列,基本上就没什么效果。 +- **Bloom Filter** 的特点就是通用,适用于各种类型、效果也比较好。缺点就是它的配置比较复杂并且计算较高。 + + + +## Join Reader Review Comment: ```suggestion ## Join Reorder ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org