Spark三种常见JOIN方式

Spark中的Join操作主要涉及SortMergeJoin、BroadcastJoin和ShuffledHashJoin三种方式。SortMergeJoin通过shuffle和排序进行数据匹配;BroadcastJoin适合小表,通过广播小表来避免shuffle;ShuffledHashJoin则在特定条件下利用哈希表进行快速匹配,但要求BuildTable不能过大。

Spark join 基本原理

Spark join的基本实现流程如下图所示,Spark将参与Join的两张表抽象为流式表(StreamTable)和查找表(BuildTable),通常系统会默认设置StreamTable为大表,BuildTable为小表。流式表的迭代器为streamItr,查找表迭代器为BuidIter。Join操作就是遍历streamIter中每条记录,然后从buildIter中查找相匹配的记录。

 

SortMergeJoin

SortMergeJoin是spark默认的join方式。

步骤:

  1. 对两张表分别进行shuffle重分区,之后将相同key的记录分到对应分区,每个分区内的数据在join之前都要进行排序,这一步对应Exchange节点和sort节点。也就是spark 的sort merge shuffle过程。

  2. 遍历流式表,对每条记录都采用顺序查找的方式从查找表中搜索,每遇到一条相同的key就进行join关联。每次处理完一条记录,只需从上一次结束的位置开始继续查找。

BroadcastJoin

BroadcastJoin也叫map join,适用于存在小表的情况。其将小表进行广播,避免shuffle的产生。web ui的sql图可以看到driver collect的时间,build建表压缩时间,broadcast广播时间。需要注意的是:在Outer类型的Join中,基表不能被广播,比如A left outer join B时,只能广播右表B。

触发场景:

  • 被广播表小于参数 spark.sql.autoBroadcastJoinThreshold``=``20971520,默认10MB。

  • 在SQL中显示添加Hint(MAPJOIN、BROADCASTJOIN或BROADCAST),比如想广播a表,就在select后加上/*+MAPJOIN(a)*/。

ShuffledHashJoin

ShuffledHashJoin避免将小表分发到各个executor上,可以减少driver和executor端的压力。

步骤:

  1. 对两张表分别进行shuffle重分区,将相同key的记录分到对应分区中,这一步对应Exchange节点

  2. 将查找表分区构造一个HashMap,然后在流式表中一行行对应查找。

要将来自BuildTable每个分区的记录放到hash表中,那么BuildTable就不能太大,否则就存不下,默认情况下hash join的实现是关闭状态,如果要使用hash join,原生spark必须满足以下四个条件:

  1. 查找表总体估计大小超过spark.sql.autoBroadcastJoinThreshold设定的值,即不满足BroadcastJoin 条件

  2. 关闭优先使用SortMergeJoin开关,spark.sql.join.preferSortMergeJoin=false

  3. 每个分区的平均大小不超过spark.sql.autoBroadcastJoinThreshold设定的值,查找表数据量 < 广播数据阈值 * shuffle的partition数。

  4. streamIter的大小是buildIter三倍以上

<think>好的,我现在需要回答用户关于Spark中5种Join策略及其使用场景的问题。首先,我得回忆一下Spark的几种Join策略,可能包括Shuffle Hash Join、Broadcast Hash JoinSort Merge Join、Broadcast Nested Loop Join和Cartesian Product Join?或者可能有其他策略,比如Skew Join?不过Skew Join可能属于优化后的策略,而不是基础策略。 用户提到了5种,所以需要确认正确的五种。根据之前的引用,用户提供的参考里有提到BHJ(Broadcast Hash Join),Skew Join,还有可能Shuffle Hash JoinSort Merge Join和Broadcast Nested Loop Join。或者可能包括Cartesian Join?或者还有其他的? 让我仔细想想。根据Spark官方文档,常见Join策略包括: 1. Broadcast Hash Join (BHJ) 2. Shuffle Hash Join 3. Sort Merge Join (SMJ) 4. Cartesian Product Join 5. Broadcast Nested Loop Join 可能这五种是主要的。此外,Skew Join可能是一种优化手段,而不是基本策略。用户的问题是需要5种策略,所以可能需要列举这五种。 接下来需要详细描述每种策略的原理、适用场景,以及可能的代码示例或配置方式。例如,Broadcast Hash Join适用于小表,当其中一个表足够小可以被广播到所有节点时使用,这样可以避免Shuffle。而Shuffle Hash Join则需要两个表都不太大,因为需要将数据按Join Key进行分区,并在每个分区内构建哈希表。Sort Merge Join通常用于大规模数据,且数据已经排序的情况,这是Spark默认的Join策略,因为适合分布式处理。Cartesian Product Join是笛卡尔积,性能最差,适用于没有Join条件的情况。Broadcast Nested Loop Join可能是在某些特定条件下的选择,比如非等值连接,并且其中一张表很小的情况。 需要确保每个策略的说明准确,并结合用户提供的引用内容。例如,引用[1]提到当小表存在时选择BHJ,引用[2]关于Skew Join处理数据倾斜,但用户的问题可能更关注基础策略,所以可能Skew Join不在五种里。引用[3]中的代码示例可能涉及不同的Join类型,但策略可能不同。 另外,用户可能需要知道如何触发这些策略,例如通过设置参数(如自动广播的阈值)或使用HINT。例如,Spark.sql.autoBroadcastJoinThreshold参数控制BHJ的使用。 现在要组织这些信息,分成五个部分,每个策略的名称、原理、适用场景,可能的使用方式或示例。同时,生成相关问题,例如性能优化、如何选择策略、处理数据倾斜等。 需要检查是否有遗漏的策略,或者是否有更常用的策略名称。例如,Shuffle Hash JoinSort Merge Join的区别,前者需要哈希表,后者需要排序。在Spark中,默认情况下可能优先使用Sort Merge Join,因为Shuffle Hash Join需要较大的内存,而Sort Merge Join更适合大规模数据。 另外,注意用户可能需要知道每种策略的优缺点,比如BHJ的网络开销小,但要求表足够小;Sort Merge Join的扩展性好,但需要排序可能带来额外开销。 总结下来,五个策略应该是: 1. Broadcast Hash Join (BHJ) 2. Shuffle Hash Join (SHJ) 3. Sort Merge Join (SMJ) 4. Cartesian Product Join 5. Broadcast Nested Loop Join (BNLJ) 或者可能还有其他?比如,在Spark 3.0之后有没有新增的策略?比如可能引入的Shuffle Sort Merge Join或者其他的?不过用户可能期望的是基础的五种,所以先按这五种来写。 在适用场景中,BHJ适用于小表,SHJ适用于中等大小的表,SMJ适用于大表,Cartesian用于无条件Join,BNLJ可能用于非等值连接且其中一表小的情况。 现在需要详细展开每个部分,确保正确性,并引用相关参考。例如,引用[1]提到当小表存在时选择BHJ,这适用于BHJ的场景。引用[2]中的Skew Join可能是在处理数据倾斜时对SMJ的优化,但可能不算作基础策略。 最后生成相关问题,例如如何选择策略,优化Join性能,处理数据倾斜等。</think>### Spark 5种 Join 策略详解及适用场景 在Spark中,Join策略的选择直接影响计算性能和资源利用率。以下是Spark支持的5种核心Join策略及其适用场景: --- #### 1. **Broadcast Hash Join (BHJ)** - **原理**:将小表广播到所有Executor节点,在每个节点上与大表的分区数据进行哈希匹配。 数学表达式:假设小表大小为$S$,广播后每个节点执行哈希查找的时间复杂度为$O(S)$。 - **适用场景**: - 其中一个表的数据量**小于** `spark.sql.autoBroadcastJoinThreshold`(默认10MB)[^1]。 - **等值Join**且无需全局Shuffle。 - **触发方式**: ```sql -- 使用HINT强制广播 SELECT /*+ BROADCAST(small_table) */ * FROM large_table JOIN small_table ON ... ``` --- #### 2. **Shuffle Hash Join (SHJ)** - **原理**:对两个表按Join Key进行Shuffle分区,在每个分区内构建哈希表进行匹配。 公式化:若两表分别分$N$个区,每个分区的哈希表构建时间为$O(K/N)$,$K$为表大小。 - **适用场景**: - 两表**均较大**但单分区数据可放入内存。 - 等值Join且无数据倾斜。 - **限制**:需手动开启(默认关闭,因内存压力大): ```sql SET spark.sql.join.preferSortMergeJoin=false; ``` --- #### 3. **Sort Merge Join (SMJ)** - **原理**:通过Shuffle将数据按Key排序后,在有序数据集上进行归并查找。 时间复杂度:$O(N \log N)$(排序) + $O(N)$(归并)。 - **适用场景**: - **大规模数据集**的等值JoinSpark默认策略)[^3]。 - 数据已按Join Key预排序时效率更高。 - **优化**:应对数据倾斜可使用`Skew Join`(拆分倾斜Key为多个子任务)[^2]。 --- #### 4. **Broadcast Nested Loop Join (BNLJ)** - **原理**:广播小表,对大表逐行扫描进行笛卡尔积匹配(支持非等值条件)。 性能公式:$O(S \times L)$,$S$为小表大小,$L$为大表行数。 - **适用场景**: - **非等值Join**(如`a.col1 > b.col2`)。 - 小表可广播且大表规模可控。 - **缺点**:计算复杂度高,需谨慎使用。 --- #### 5. **Cartesian Product Join** - **原理**:直接计算两表的笛卡尔积,无任何优化。 公式:结果集大小为$M \times N$($M$和$N$为两表行数)。 - **适用场景**: - **无Join条件**的跨表关联。 - 测试或极小数据集场景。 - **触发条件**:显式使用`CROSS JOIN`语法。 --- ### 策略选择流程图 ```plaintext 是否等值Join? ├─ 是 → 能否广播小表? → BHJ ├─ 否 → BNLJ或Cartesian ├─ 中等规模 → SHJ └─ 大规模 → SMJ(默认) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LkChase

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值