Spark 浅谈Spark中的各种join
众所周知,Join的种类丰富:
按照**关联形式(**Join type)划分:
有内关联,外关联,左关联,右关联,半关联,逆关联等,由业务逻辑决定的关联形式决定了Spark任务的运行结果;
按照关联机制(Join Mechanisms)划分:
有NLJ(Nested Loop Join) , SMJ(Sort Merge Join)和HJ(Hash Join),由数据内容决定的实现机制,则决定了Spark任务的运行效率;
关联形式
Spark支持的关联形式:
关联形式 | Join Type关键字 |
---|---|
内连接 | inner |
左外关联 | left / left outer / left_outer |
右外关联 | right/ right outer/right_outer |
全外关联 | outer/ full / full outer / full_outer |
左半关联 | left semi/ left_semi |
左逆关联 | left anti / left_anti |
交叉关联 | crossJoin |
数据准备
import spark.implicits._
import org.apache.spark.sql.DataFrame// 创建员工信息表
val seq = Seq((1, "Mike", 28, "Male"), (2, "Lily", 30, "Female"), (3, "Raymond", 26, "Male"), (5, "Dave", 36, "Male"))
val employees: DataFrame = seq.toDF("id", "name", "age", "gender")// 创建薪资表
val seq2 = Seq((1, 26000), (2, 30000), (4, 25000), (3, 20000))
val salaries:DataFrame = seq2.toDF("id", "salary")// 左表
salaries.show/** 结果打印
+---+------+
| id|salary|
+---+------+
| 1| 26000|
| 2| 30000|
| 4| 25000|
| 3| 20000|
+---+------+
*/// 右表
employees.show/** 结果打印
+---+-------+---+------+
| id| name|age|gender|
+---+-------+---+------+
| 1| Mike| 28| Male|
| 2| Lily| 30|Female|
| 3|Raymond| 26| Male|
| 5| Dave| 36| Male|
+---+-------+---+------+
*/
内连接(Inner join)
内连接是默认关联形式,可以省略写成join. 左右表按照join key连接, 舍弃未匹配的行,仅仅保留左右表中满足关联条件的那些数据记录
.
// 内关联
val jointDF: DataFrame = salaries.join(employees, salaries("id") === employees("id"), "inner")jointDF.show/** 结果打印
+---+------+---+-------+---+------+
| id|salary| id| name|age|gender|
+---+------+---+-------+---+------+
| 1| 26000| 1| Mike| 28| Male|
| 2| 30000| 2| Lily| 30|Female|
| 3| 20000| 3|Raymond| 26| Male|
+---+------+---+-------+---+------+
*/
外连接(Outer join)
val jointDF: DataFrame = salaries.join(employees, salaries("id") === employees("id"), "left")jointDF.show/** 结果打印
+---+------+----+-------+----+------+
| id|salary| id| name| age|gender|
+---+------+----+-------+----+------+
| 1| 26000| 1| Mike| 28| Male|
| 2| 30000| 2| Lily| 30|Female|
| 4| 25000|null| null|null| null|
| 3| 20000| 3|Raymond| 26| Male|
+---+------+----+-------+----+------+
*/
外连接的左右指的是不满足join条件的数据来自于哪张表,上述的"left"左外连接,就让第三行数据来自于左表.
半关联(semi join)
// 左半关联
val jointDF: DataFrame = salaries.join(employees, salaries("id") === employees("id"), "leftsemi")jointDF.show/** 结果打印
+---+------+
| id|salary|
+---+------+
| 1| 26000|
| 2| 30000|
| 3| 20000|
+---+------+
*/
半关联是inner join的一半返回,left semi join返回左表数据, right semi join返回右表数据
逆关联(anti join)
// 左逆关联
val jointDF: DataFrame = salaries.join(employees, salaries("id") === employees("id"), "leftanti")jointDF.show/** 结果打印
+---+------+
| id|salary|
+---+------+
| 4| 25000|
+---+------+
*/
逆关联返回的是未关联上的行.
关联机制
假设我们将join表称为"驱动表",将被join的表称为"基表",基于这两个称呼:
spark的关联机制
join实现机制 | 工作原理 | 适用场景 |
---|---|---|
Nested Loop Join | 在驱动表与基表之上,使用嵌套的双层for循环实现关联,效率最低,算法复杂度为O(M*N) | 其他策略不使用的情况 |
Sort Merge Join | 首先将两张表排序,然后以双指针遍历的方式实现关联,关联阶段的算法复杂度为O(M+N) | 两张表都按照join key排序的情况 |
Hash Join | 关联过程分为两个阶段 Build + Probe , Build 使用Hash算法生成哈希表O(N),Probe 查表获得值O(M) | 哈希表较小且易生成. |
关联策略
Spark的关联策略对比
对比项 | Shuffle Join | Broadcast Join |
---|---|---|
实现原理 |
* 根据Join Keys 计算哈希值 * 将哈希值按照并行度(parallelism)取模 |
封装一张小表为广播变量,发送到所有Executor. |
优点 | 不论数据的体量是大是小、不管内存是否足够,Shuffle Join 在功能上都能成功地完成数据关联的计算 | 通过分发较小数据表,SQL的执行性能高效. |
适用场景 | 任何场景都能完成 | 广播表较小 |
前提条件 | 无 | 基表需要足够小(小于Excutor内存) |
缺点 | shuffle IO 带来的性能瓶颈 | 无 |
关联机制 x 关联策略
3种关联机制跟 2中关联策略的组合,出现了6中join.由于Broadcast SMJ < Broadcast HJ ,去掉毫无用武之处的Broadcast SMJ,余下了以下5种join方式.
join方式 | 原理 | 适用场景 |
---|---|---|
Broadcast HJ | 基表加工成哈希表,广播到所有Executor,内部查表连接 | 基表小,等值join查表快 |
Broadcast NLJ | 广播小表,Excutor内部用双重循环连接 | 基表小,可以用于不等值join |
Shuffle SMJ | 因为Shuffle要按照join key排序,所以spark 优先选择SMJ | 基表大 |
Shuffle HJ | 因为SMJ的原因,Shuffle HJ基本不用 | 同Shuffle SMJ |
Shuffle NLJ | 两张表都比较大,而且join是非等值join | 其他场景都不适用的情况 |
Spark 浅谈Spark中的各种join相关推荐
- mysql inner和left优化_浅谈mysql中的left join和inner join性能及优化策略
前言 看一下 下面的sql语句:select * from a left join b on a.x = b.x left join c on c.y = b.y 这样的多个left join组合的时 ...
- 浅谈Spark应用程序的性能调优
浅谈Spark应用程序的性能调优 :http://geek.csdn.net/news/detail/51819 下面列出的这些API会导致Shuffle操作,是数据倾斜可能发生的关键点所在 1. ...
- oracle hash join outer,CSS_浅谈Oracle中的三种Join方法,基本概念
Nested loop join:
Outer - phpStudy...
浅谈Oracle中的三种Join方法 基本概念 Nested loop join: Outer table中的每一行与inner table中的相应记录join,类似一个嵌套的循环. Sort mer ...
- python文件路径拼接多出斜杠_浅谈python中拼接路径os.path.join斜杠的问题
浅谈python中拼接路径os.path.join斜杠的问题 调试程序的过程中,发现通过os.path.join拼接的路径出现了反斜杠 directory1='/opt/apps/upgradePac ...
- python的re2和re区别_浅谈Python中re.match()和re.search()的使用及区别
1.re.match()fvk免费资源网 re.match()的概念是从头匹配一个符合规则的字符串,从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None.fvk免费资源网 包含的参数如下: ...
- python读取图像数据流_浅谈TensorFlow中读取图像数据的三种方式
本文面对三种常常遇到的情况,总结三种读取数据的方式,分别用于处理单张图片.大量图片,和TFRecorder读取方式.并且还补充了功能相近的tf函数. 1.处理单张图片 我们训练完模型之后,常常要用图片 ...
- js打印线程id_浅谈python中的多线程和多进程(二)
原创:hxj7 本文继续分享一个关于python多线程和多进程区别的例子 前文<浅谈python中的多线程和多进程>中我们分享过一个例子,就是分别利用python中的多线程和多进程来解决高 ...
- 获得进程id_浅谈python中的多线程和多进程(二)
原创:hxj7 本文继续分享一个关于python多线程和多进程区别的例子 前文<浅谈python中的多线程和多进程>中我们分享过一个例子,就是分别利用python中的多线程和多进程来解决高 ...
- 浅谈CTF中各种花式绕过的小trick
文章目录 浅谈CTF中各种花式绕过的小trick 前言 md5加密bypass 弱比较绕过 方法一:0e绕过 方法二:数组绕过 强比较绕过 方法:数组绕过 md5碰撞绕过 方法:使用Fastcoll生 ...
最新文章
- java b2b b2c o2o分布式电子商务云平台
- springboot集成freemarker 配置application.properties详解
- 在RHEL5.0中用YUM解决RPM包的依赖关系
- 计算机内存知识txt,计算机新手必备内存实用知识.docx
- 机器学习常见知识点自查50问与答
- xhprof在windows下面的安装和使用[上](windows版本)
- 听说java又过气了?看我运用大数据分析2019年java发展趋势!
- JS工具类——Select操作类
- 分布式技术追踪 2018年第二期
- android 模拟器 403,Android403R2模拟器安装.doc
- 2018仲恺农业计算机大类录取,仲恺农业工程学院2019录取分数线预测
- 踩坑指南!anaconda新建环境出错解决!又是猛男落泪的一天!
- 「转录组」WGCNA实战原理两不误
- Python 中拼音库 PyPinyin 的使用
- 什么是软件验收测试?验收测试的标准和流程介绍
- 百度CarLife Android车机端黑屏问题
- 计算机键盘怎么换键,电脑修改键盘按键的方法
- python正则表达式——区间的表达方式
- MATLAB轨迹规划 发给ROS中机器人实现仿真运动
- 中国大学MOOC·Python网络爬虫与信息提取(一)