首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >SparkSQL 如何选择 join 策略

SparkSQL 如何选择 join 策略

作者头像
kk大数据
发布于 2024-02-28 09:44:53
发布于 2024-02-28 09:44:53
55001
代码可运行
举报
文章被收录于专栏:kk大数据kk大数据
运行总次数:1
代码可运行

一、前言

Join 操作是大数据分析领域必不可少的操作,本文将从原理层面介绍 SparkSQL 支持的五大连接策略及其应用场景。

SparkSQL 内置了五种连接策略,如下所示

1、Broadcast Hash Join(BHJ)

2、Shuffle Hash Join

3、Shuffle Sort Merge Join(SMJ)

4、Cartesian Product Join

5、Broadcast Nested Loop Join(BNLJ)

二、影响策略选择因素

(1)是否为等值连接

等值连接是在连接条件中只有 equals 比较,非等值连接包含除 equals 以外的任何比较,例如 >,<,>=,<=。对于非等值连接,SparkSQL 只支持 Broadcast Nested Loop Join 和 Cartesian Product Join。其他的连接策略都支持等值连接。

(2)用户自定义的连接提示(hint)

Spark 3.0 支持以下的提示(在 hints.scala 文件中):

BROADCAST, SHUFFLE_MERGE, SHUFFLE_HASH, SHUFFLE_REPLICATE_NL

(3)连接的数据集大小

连接策略的选择最重要的因素就是数据集的大小,核心策略就是避免 shuffle 和 排序操作,这些操作非常昂贵,对查询的性能影响较大。

三、流程图

绘制了一个流程图来描述 Spark SQL 是如何选择连接策略的:

四、策略选择过程

首先判断是否为等值连接,会进入不同的主流程。

1、等值连接

(1)开发人员指定的连接提示(hint)具有最高的优先权

对于 BROADCAST 提示,选择 Broadcast Hash Join 策略,当 BROADCAST 提示在连接的两边都被指定时,选择数据集较小的那一边;

对于 SHUFFLE_HASH 提示,选择 Shuffle Hash Join 策略,当 SHUFFLE_HASH 提示在连接两边都被指定时,选择数据集较小的那一边;

对于 SHUFFLE_MERGE 提示,如果连接键是可排序的,选择 Shuffle Sort Merge Join 策略;

对于 SHUFFLE_REPLICATE_NL 提示,如果连接类型时内部连接,选择 Cartesian Product Join 策略。

(2)接下来判断数据集的大小

当连接数据集中至少有一方小到可以收集到 driver 端,然后广播到每个 executor 时,Broadcast Hash Join 是首选策略。可以被广播的数据集的阈值大小默认是 10M,可以通过 spark.sql.autoBroadcastJoinThreshold 参数来配置,基于 driver 和 executor 端的可用内存。

当 BroadcastExchange 操作符被执行时,它首先将数据集 collect 到 driver 端,然后 广播到所有的 Executor 节点。注意数据集的行数不能超过 MAX_BROADCAST_TABLE_ROWS (3.4亿行),否则会无法广播。

在 Executor 端,广播的数据集被用作连接的 buildTable,而最初存在于 executor 的数据集,即连接的大表,被用作连接的 StreamTable,连接过程中遍历 StreamTable,在 buildTable 中查找匹配的行。

(3)如果选择 BroadcastHash 策略没有被满足,则判断是否将 Shuffle Sort Merge Join 策略设置为首选,由 spark.sql.join.preferSortMergeJoin 参数控制,默认为 true。

如果这个参数被显式设置了 false,则判断是否使用 Shuffle Hash Join 策略的条件:至少有一个连接数据集需要小到足以建立一个 hash table(使的较小的数据集可以加载到内存中)。其大小应该小于广播阈值和 shuffle 分区数的乘积

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

private def canBuildLocalHashMap(plan: LogicalPlan): Boolean = {  
  plan.stats.sizeInBytes < conf.autoBroadcastJoinThreshold * conf.numShufflePartitions  
}

另外较大的数据集至少应该是较小数据集大小的3倍以上,此时收益比较大

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private def muchSmaller(a: LogicalPlan, b: LogicalPlan): Boolean = {  
  a.stats.sizeInBytes * 3 <= b.stats.sizeInBytes  
}

Shuffle Hash Join 执行时,会对两个数据集进行 shuffle,以便将两边数据集中,具有相同连接键的行放在同一个 executor 中。较小的数据集作为 buildTable,较大的数据集作为 StreamTable。

(4)如果以上条件没有被满足,则开始判断是否使用 Shuffle Sort Merge Join 为了使用基于排序的连接算法,连接键必须是可排序的

Shuffle Sort Merge Join 不需要将任何数据集装入内存,所以连接数据集大小没有限制。基于排序的连接算法没有基于 hash 的连接快,但它通常比嵌套循环的连接算法表现更好,因此基于性能和灵活性的双重考虑,Sort Merge Join 是一个折中的方案。

Shuffle Sort Merge Join 也需要对连接的数据集进行shuffle,以便将两边数据集中具有相同连接键的行放在同一个 Executor 中,此外,每个分区的数据都需要按连接键进行升序排序。

两个连接数据集中的任何一个都可以作为 buildTable 或者 streamTable 使用。当一个数据集被作为 streamTable 时,它被按顺序逐行迭代。对于每个 streamTable 行,buildTable 也是按顺序逐行搜索的,由于它们都是排了序的,当连接过程转义到下一行的 streamTable 时,buildTable 不必从第一行开始,而只需要从上一个匹配到的行继续搜索即可。

(5)如果 Shuffle Sort Merge Join 策略的条件没有被满足,并且 joinType 是 InnerLinke,则会使用 Cartesian Product Join 策略,可能通常没有定义连接条件。笛卡尔积会非常慢,并且容易 oom,要慎重使用;

(6)如果以上条件都没有满足,则会选择 BroadcastNestedLoopJoin ,此时会将 streamTable 和 buildTable 进行嵌套循环

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

private def innerJoin(relation: Broadcast[Array[InternalRow]]): RDD[InternalRow] = {  
  streamed.execute().mapPartitionsInternal { streamedIter =>  
    val buildRows = relation.value  
    val joinedRow = new JoinedRow  
  
    streamedIter.flatMap { streamedRow =>  
      val joinedRows = buildRows.iterator.map(r => joinedRow(streamedRow, r))  
      if (condition.isDefined) {  
        joinedRows.filter(boundCondition)  
      } else {  
        joinedRows  
      }  
    }  
  }
  

这种策略的性能也会非常糟糕。

2、非等值连接

只有两种策略支持非等值连接:Cartesian Product Join和Broadcast Nested Loop Join。

如果在连接查询中指定了连接提示,请根据连接提示选择相应的连接策略。否则,如果数据集的一侧或两侧小到可以广播,则选择Broadcast Nested Loop Join策略并广播较小的数据集。如果没有足够小的数据集可以广播,则检查JointType是否为InnerLike,如果是,则选择Cartesian Product Join策略,否则就选择Broadcast Nested Loop Join策略作为最终方案。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-02-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 KK架构 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Spark Join 源码剖析①
在 Spark SQL 中,参与 Join 操作的两张表分别被称为流式表(StreamTable)和构件表(BuildTable),不同表的角色在 Spark SQL 中会通过一定的策略进行设定。通常来讲,系统会将大表设置为 StreamTable,小表设置为 BuildTable。流式表的迭代器为 streamIter,构建表的迭代器为 buildIter。遍历 streamIter 的每一条记录,然后在 buildIter 中查找匹配的记录。这个查找过程称为 build 过程。每次 build 操作的结果为一条 JoinedRow(A, B),其中 A 来自 streamedIter,B 来自 buildIter。
codingforfun
2022/05/23
8920
Spark Join 源码剖析①
Spark SQL是如何选择join策略的?
我们都知道,Spark SQL上主要有三种实现join的策略,分别是Broadcast hash join、Shuffle hash join、Sort merge join。那Catalyst是依据什么样的规则来选择join策略的?本文来简单补个漏。
王知无-import_bigdata
2020/05/07
2.9K0
Spark SQL如何选择join策略
众所周知,Catalyst Optimizer是Spark SQL的核心,它主要负责将SQL语句转换成最终的物理执行计划,在一定程度上决定了SQL执行的性能。
大数据学习与分享
2020/08/10
1.3K0
SparkSQL Join深度解析:三种实现方式全揭秘
SparkSQL 现在基本上可以说是离线计算的大拿了,所以掌握了 SparkSQL 的 Join 也就相当于掌握了这位大拿。
shengjk1
2025/05/16
1900
SparkSQL Join深度解析:三种实现方式全揭秘
【Spark重点难点06】SparkSQL YYDS(中)!
在上节课中我们讲解了Spark SQL的来源,Spark DataFrame创建的方式以及常用的算子。这节课继续讲解Spark SQL中的Catalyst优化器和Tungsten,以及Spark SQL的Join策略选择。
王知无-import_bigdata
2021/12/16
7770
【Spark重点难点06】SparkSQL YYDS(中)!
SparkSql中join和shuffle知识点梳理
sparksql中有一些容易混淆的概念,大家在面试时也会经常被问到join和shuffle相关的问题:
数据仓库践行者
2022/11/25
1.3K0
SparkSql中join和shuffle知识点梳理
五万字 | Spark吐血整理,学习与面试收藏这篇就够了!
一、Spark 基础 二、Spark Core 三、Spark SQL 四、Spark Streaming 五、Structured Streaming 六、Spark 两种核心 Shuffle 七、Spark 底层执行原理 八、Spark 数据倾斜 九、Spark 性能调优 十、Spark 故障排除 十一、Spark大厂面试真题
五分钟学大数据
2021/09/22
4.8K0
【硬刚大数据】从零到大数据专家面试篇之SparkSQL篇
Spark SQL是一个用来处理结构化数据的Spark组件,前身是shark,但是shark过多的依赖于hive如采用hive的语法解析器、查询优化器等,制约了Spark各个组件之间的相互集成,因此Spark SQL应运而生。
大数据真好玩
2021/09/18
2.6K0
【硬刚大数据】从零到大数据专家面试篇之SparkSQL篇
SparkSQL Join的源码分析
SparkSQL 现在基本上可以说是离线计算的大拿了,所以掌握了 SparkSQL 的 Join 也就相当于掌握了这位大拿。
shengjk1
2025/05/16
520
自己工作中超全spark性能优化总结
Spark是大数据分析的利器,在工作中用到spark的地方也比较多,这篇总结是希望能将自己使用spark的一些调优经验分享出来。
guichen1013
2020/11/25
2K0
自己工作中超全spark性能优化总结
Spark join种类(>3种)及join选择依据
join是作为业务开发绕不开的SQL话题,无论是传统的数据库join,还是大数据里的join。
Spark学习技巧
2021/03/05
1.1K0
Spark join种类(>3种)及join选择依据
SparkSQL中产生笛卡尔积的几种典型场景以及处理策略
【前言:如果你经常使用Spark SQL进行数据的处理分析,那么对笛卡尔积的危害性一定不陌生,比如大量占用集群资源导致其他任务无法正常执行,甚至导致节点宕机。那么都有哪些情况会产生笛卡尔积,以及如何事前"预测"写的SQL会产生笛卡尔积从而避免呢?(以下不考虑业务需求确实需要笛卡尔积的场景)】
大数据学习与分享
2020/08/10
2.4K0
SparkSQL中产生笛卡尔积的几种典型场景以及处理策略
Spark难点 | Join的实现原理
当前SparkSQL支持三种join算法:Shuffle Hash Join、Broadcast Hash Join以及Sort Merge Join。其中前两者归根到底都属于Hash Join,只不过载Hash Join之前需要先Shuffle还是先Broadcast。其实,Hash Join算法来自于传统数据库,而Shuffle和Broadcast是大数据在分布式情况下的概念,两者结合的产物。因此可以说,大数据的根就是传统数据库。Hash Join是内核。
王知无-import_bigdata
2019/11/18
1.7K0
MySQL 的 join 功能弱爆了?
关于MySQL 的 join,大家一定了解过很多它的“轶事趣闻”,比如两表 join 要小表驱动大表,阿里开发者规范禁止三张表以上的 join 操作,MySQL 的 join 功能弱爆了等等。这些规范或者言论亦真亦假,时对时错,需要大家自己对 join 有深入的了解后才能清楚地理解。
程序员历小冰
2020/11/11
1.1K0
程序员必备的数据库知识 2:Join 算法
连接(Join)是关系数据库重要特性,它和事务常被作为数据库与文件系统的两个重要区别项。程序员江湖一直流传着某某 baba 的神秘开发宝典,其中数据库部分有重要一条避免过多表的 Join,奈何 Join 特性实在是好用,广大程序员们无视着宝典的谆谆教诲,依旧每天乐此不疲的使用这 Join 特性。那数据库有哪些连接算法呢?它们的实现方式是怎样呢?它们之间又有什么区别呢?为什么需要这么多不同的连接算法呢?如果你也好奇这些问题,那么请继续往下阅读,本文将逐一回答上述问题。
NineData
2023/02/08
9030
程序员必备的数据库知识 2:Join 算法
多表连接的三种方式详解 hash join、merge join、 nested loop
在多表联合查询的时候,如果我们查看它的执行计划,就会发现里面有多表之间的连接方式。多表之间的连接有三种方式:Nested Loops,Hash Join 和 Sort Merge Join.具体适用哪种类型的连接取决于
NateHuang
2020/01/13
6.8K0
多表连接的三种方式详解 hash join、merge join、 nested loop
spark 多表 join
1.Broadcast Hash Join(小表广播,小表Join大表)(分布式改造)
用户6404053
2019/11/03
3.4K0
spark 多表 join
MySQL Hash Join实现分析
提示:公众号展示代码会自动折行,建议横屏阅读 「前言」 连接操作是一种数据库中最基本的操作,连接算法的执行效率直接影响到整个数据库的效率、吞吐和资源。通常商业数据库系统一般有三种主流的连接实现:Nested Loop Join、Hash Join和Sort Merge Join。本文概述目前主流的Hash Join实现方式,以及分析MySQL中Hash Join的实现方式。 MySQL 8.0.18 版本增加了对Hash Join算法的支持,在此之前,连接算法仅支持嵌套循环连接 Nested Loop J
腾讯数据库技术
2021/12/30
2.6K1
干货|Spark优化之高性能Range Join
Carmel是eBay内部基于Apache Spark打造的一款SQL-on-Hadoop查询引擎。通过对Apache Spark的改进,我们为用户提供了一套高可用高性能的服务,以满足eBay内部大量分析型的查询需求(如今单日查询量已超过30万)。
Spark学习技巧
2022/01/13
1.9K0
干货|Spark优化之高性能Range Join
MySQL 8.0 新特性:引人注目的哈希连接(Hash Join)
blog.csdn.net/horses/article/details/102690076
肉眼品世界
2020/11/11
7810
MySQL 8.0 新特性:引人注目的哈希连接(Hash Join)
相关推荐
Spark Join 源码剖析①
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验