Spark Join

news2024/9/23 17:20:07

Spark Join

  • 关联形式
    • 内关联
    • 外关联
      • 左外关联
      • 右外关联
      • 全外关联
    • 左半/逆关联
  • 关联机制
    • NLJ
    • SMJ
    • HJ
  • 分发模式
  • Join 选择
    • 等值 Join
    • 不等值 Join

Join 按照关联形式(Join Types)划分 : 内关联、外关联、左关联、右关联

  • Join 按实现机制划分 : NLJ (Nested Loop Join) 、SMJ (Sort Merge Join) 、HJ(Hash Join)
  • Join 按分发模式划分 : Shuffle Join、Broadcast Join

关联形式

Spark SQL支持的关联形式 :

关联形式Join Type效果
内关联inner结果集中只包含满足关联条件的数据
左外关联left/leftouter/left_outer内关联结果集+左表中不满足关联条件的剩余数据
右外关联right/rightouter/right_outer内关联结果集 + 右表中不满足关联条件的剩余数据
全外关联outer/full/fullouter/full_outer内关联结果集 + 左、右表中不满足关联条件的剩余数据
左半关联leftsemi/left_semi内关联结果集,但只保留左表部分的数据
左逆关联leftanti /left_anti左表中不满足关联条件的数据

内关联

内关联的效果 : 仅保留左右表中满足关联条件的那些数据记录

  • 在员工表与薪资表中,只有 1、2、3 这三个值同时存在它们各自的 id 中。所以结果集中就只有 1、2、3 的这三条数据
// 左表
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|
+---+-------+---+------+
*/

// 内关联
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|
+---+------+---+-------+---+------+
*/

外关联

外关联能细分 3 种形式:左外关联、右外关联、全外关联

左外关联

左外关联,用 left/ leftouter/ left_outer

  • 左外关联的结果集 : 内关联结果集 + 左表的不满足关联条件的剩余数据
  • 不存在的记录,在结果集中的所有字段值均为空值 null
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|
+---+------+----+-------+----+------+
*/

右外关联

右外关联,用 right/ rightouter/ right_outer

  • 右外关联的结果集:内关联的结果集 + 右表的剩余数据
  • 不存在的记录,在结果集中的所有字段值均为空值 null
val jointDF: DataFrame = 
	salaries.join(employees, salaries("id") === employees("id"), "right")

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|
|null| null| 5| Dave| 36| Male|
+----+------+---+-------+---+------+
*/

全外关联

全外关联,用 full/ outer/ ullouter/ full_outer

  • 全外关联的结果集:内关联的结果 + 那些不满足关联条件的左右表剩余数据
val jointDF: DataFrame = 
	salaries.join(employees, salaries("id") === employees("id"), "full")

jointDF.show
/** 结果打印
+----+------+----+-------+----+------+
| id|salary| id| name| age|gender|
+----+------+----+-------+----+------+
| 1| 26000| 1| Mike| 28| Male|
| 3| 20000| 3|Raymond| 26| Male|
|null| null| 5| Dave| 36| Male|
| 4| 25000|null| null|null| null|
| 2| 30000| 2| Lily| 30|Female|
+----+------+----+-------+----+------+
*/

左半/逆关联

左半关联,用 leftsemi/left_semi

  • 左半关联的结果集 : 内关联结果集的子集,但仅保留左表数据
// 左半关联
val jointDF: DataFrame = 
	salaries.join(employees, salaries("id") === employees("id"), "left_semi")

jointDF.show
/** 结果打印
+---+------+
| id|salary|
+---+------+
| 1| 26000|
| 2| 30000|
| 3| 20000|
+---+------+
*/

左逆关联,用 leftanti/left_anti

  • 左逆关联的结果集 : 不满足条件结果集的子集,但仅保留左表数据
// 左逆关联
val jointDF: DataFrame = 
	salaries.join(employees, salaries("id") === employees("id"), "left_anti")

jointDF.show
/** 结果打印
+---+------+
| id|salary|
+---+------+
| 4| 25000|
+---+------+
*/

关联机制

Join 有 3 种实现机制 :

  • NLJ(Nested Loop Join): 嵌套循环连接
  • SMJ(Sort Merge Join): 排序归并连接
  • HJ(Hash Join): 哈希连接

俗定 : 左表 = 驱动表,右表 = 基表

  • 驱动表较大,主动扫描数据的一边
  • 基表较小,被动参与数据扫描的一方
Join实现机制范围效率工作原理
Nested Loop Join全部关联最差用嵌套循环来实现关联,效率最低,算法复杂度为 O(M * N)
Sort Merge Join等值关联次优先将两表排序,再用游标滑动实现关联,算法复杂度为 O(M + N)
Hash Join等值关联最优关联过程分两阶段:Build:用哈希算法对基表建立哈希表。Probe:遍历驱动表每条数据,动态计算哈希值,再找哈希表来实现关联计算。复杂度为 O(M)

NLJ

NLJ (Nested Loop Join ) 的实现机制:用外、内两个嵌套的 for 循环,来依次扫描驱动表与基表中的数据记录

  • 外层的 for 循环遍历驱动表的每一条数据
  • 驱动表中的每条数据,内层 for 逐条扫描基表的所有记录,依次判断记录的 id 字段值是否满足关联条件
  • 驱动表有 M 行,基表有 N 行,NLJ 计算复杂度是 O(M * N)

在这里插入图片描述

SMJ

SMJ (Sort Merge Join) 的实现思路 : 先排序、再归并

  • 对关联的两张表,SMJ 先各自排序,然后再使用独立的游标,对排好序的两张表做归并关联
  • SMJ 算法的计算复杂度为 O(M + N)

游标对比的 3 种情况:

  • 满足关联条件:两边的 id 相等,把两边的数据记录拼接并输出,然后驱动表的游标下滑
  • 不满足关联条件:驱动表 id 值 < 基表的 id 值,驱动表的游标下滑
  • 不满足关联条件 : 驱动表 id 值 > 基表的 id 值,基表的游标下滑

在这里插入图片描述

HJ

HJ (Hash Join) 的设计初衷 : 以空间换时间,将基表的计算复杂度降到 O(1)

HJ 的计算的两个阶段:Build 阶段和 Probe 阶段

  • Build 阶段:在基表上,用自定的哈希构建哈希表。哈希表的 Key 是 id 哈希后的哈希值,哈希表的 Value 是基表数据
  • Probe 阶段:依次遍历驱动表的每条数据。先用同样的哈希,得到哈希值。然后用哈希值去查询刚 Build 好的哈希表。当查询失败,就跳过;当查询成功,就对比两边的 Join Key。如果 Join Key 一致,就拼接并输出

在这里插入图片描述

分发模式

Join 按照分发模式划分 : Shuffle Join、Broadcast Join

  • Shuffle Join :任何情况,都能完成数据关联的计算
  • Broadcast Join : 广播数据表的全量数据到 Driver 的内存、以及各个 Executors 的内存
Join策略前提条件优势劣势
Shuffle Join适用范围广,不受数据体量、内存大小会有 l/O开销,容易性能瓶颈
Broadcast Join基表 < Executors 内存只需广播基表,消除驱动表的 Shuffle 过程,执行效率高

用 Shuffle 完成数据关联 :

在这里插入图片描述

用广播机制完成数据关联 :

在这里插入图片描述

6 种分布式 Join :

在这里插入图片描述

Spark SQL 的5 种 Join :

在这里插入图片描述

Join 选择

关联条件Join 策略排序
等值关联Broadcast HJ > Shuffle SMJ > Shuffle HJ
不等值关联Broadcast NLJ > Shuffle NLJ

等值 Join

等值数据关联时,Spark 会按照 BHJ > SMJ > SHJ 的顺序选择 Join 策略

BHJ 效率最高,前提条件:

  • 连接类型不能是全连接(Full Outer Join)
  • 基表要足够小,能放到广播变量

SHJ 前提条件:

  • 外表大小大于内表的 3 倍上
  • 内表数据分片的平均大小 < 广播变量阈值

spark.sql.join.preferSortMergeJoin为 False 时,Spark SQL 才会先尝试 SHJ

不等值 Join

不等值 Join 只能用 BNLJ和 CPJ

  • Spark SQL 会按照 BNLJ > CPJ 的顺序尝试
  • BNLJ 前提条件:内表小能放进广播变量

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/392435.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【操作系统原理实验】页面替换策略模拟实现

选择一种高级语言如C/C等&#xff0c;编写一个页面替换算法的模拟实现程序。1) 设计内存管理相关数据结构&#xff1b;2) 随机生成一个页面请求序列&#xff1b;3) 设置内存管理模拟的关键参数&#xff1b;4) 实现该页面置换算法&#xff1b;5) 模拟实现给定配置请求序列的换页…

【python socket】实现websocket服务端

一、获取握手信息首先通过如下代码&#xff0c;我们使用socket来获取客户端的握手信息import socketsock socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(("127.0.0.1", 8002)) sock.li…

启动项管理工具Autoruns使用实验(20)

实验目的 &#xff08;1&#xff09;了解注册表的相关知识&#xff1b; &#xff08;2&#xff09;了解程序在开机过程中的自启动&#xff1b; &#xff08;3&#xff09;掌握Autoruns在注册表和启动项方面的功能&#xff1b;预备知识 注册表是windows操作系统中的一个核心数据…

Android Framework-Android启动过程

第一个系统进程&#xff08;init&#xff09; Android设备的启动必须经历3个阶段&#xff0c;即Boot Loader、Linux Kernel和Android系统服务&#xff0c;默认情况下它们都有各自的启动界面。严格来说&#xff0c;Android系统实际上是运行于Linux内核之上的一系列“服务进程”…

元宇宙XR应用,如何迎接大规模普及的时代?

未来&#xff0c;具有互动性、沉浸感的元宇宙/XR应用将逐渐成为主流&#xff0c;这个趋势已毋庸置疑。 然而&#xff0c;在大趋势下&#xff0c;大众终端用户普遍设备能力不足、网络传输时延、GPU算力分配限制等技术挑战&#xff0c;依然是元宇宙/XR应用在大众广泛渗透的瓶颈。…

【vulhub漏洞复现】Fastjson 1.2.24反序列化漏洞

一、漏洞详情Fastjson 是一个 Java 库&#xff0c;可以将 Java 对象转换为 JSON 格式&#xff0c;也可以将 JSON 字符串转换为 Java 对象。漏洞成因&#xff1a;目标网站在解析 json 时&#xff0c;未对 json 内容进行验证&#xff0c;直接将 json 解析成 java 对象并执行&…

国产数字源表在压力传感器电阻测量上的应用

压力传感器分类压力传感器(Pressure Transducer)是能感受压力信号&#xff0c;并能按照一定的规律将压力信号转换成可用的输出的电信号的器件或装置,压力传感器通常由压力敏感元件和信号处理单元组成。常见的压力传感器有四种:应变式压力传感器、压阻式压力传感器、电容式压力传…

OpenMMLab 目标检测

OpenMMLab 目标检测1. 目标检测简介1.1 滑窗2. 基础知识2.1 边界框&#xff08;Bounding Box&#xff09;3. 两阶段目标检测算法3.1 多尺度检测技术4. 单阶段目标检测算法4.1 YOLO: You Only Look Once (2015)4.2 SSD: Single Shot MultiBox Detetor (2016)5. 无锚框目标检测算…

Nginx的搭建与核心配置

目录 一.Nginx是什么&#xff1f; 1.Nginx概述 2.Nginx模块与作用 3.Nginx三大作用&#xff1a;反向代理、负载均衡、动静分离 二.Nginx和Apache的差异 三.安装Nginx 1.编译安装 2.yum安装 四.Nginx的信号使用 五.Nginx的核心配置指令 1.访问状态统计配置 2.基于授…

非华为电脑安装华为电脑管家以及注意事项

非华为电脑安装华为电脑管家前言安装注意事项效果展示前言 非华为电脑是可以安装华为电脑管家的&#xff0c;不过部分功能可能不兼容。值得一提的是&#xff0c;超级终端、多屏协同、文件共享、远程控制等功能大部分电脑是可以使用的&#xff0c;本人在联想ThinkBook 15电脑上…

【CS144】Lab1总结

Lab1Lab汇总概述具体实现Lab汇总 概述 lab1要求实现一个字符串的装配器&#xff0c;用于将TCPTCPTCP接收方接收到的字节流拼接起来&#xff0c;并缓存一定量的乱序到达的字节&#xff0c;便于TCPTCPTCP接收方相关功能的实现。 具体实现 该装配器实现的重点是push_substring…

Java线程池使用与原理解析2(自定义线程池、合适的线程数量、线程池阻塞队列、线程拒绝策略)

在上篇我们学习了线程池各个参数的含义&#xff0c;线程池任务处理流程&#xff0c;使用线程池的好处等内容&#xff0c;本篇我们学习如何创建一个适合我们业务的线程池。为此&#xff0c;我们有必要先学习一下如何大概确定我们线程池核心线程数、怎么设置阻塞队列的类型与大小…

Malware Dev 04 - 隐匿之 ETW(Event Tracing for Windows)Bypass

写在最前 如果你是信息安全爱好者&#xff0c;如果你想考一些证书来提升自己的能力&#xff0c;那么欢迎大家来我的 Discord 频道 Northern Bay。邀请链接在这里&#xff1a; https://discord.gg/9XvvuFq9Wb我拥有 OSCP&#xff0c;OSEP&#xff0c;OSWE&#xff0c;OSED&…

使用leangoo领歌单团队敏捷开发项目管理

概述单团队敏捷开发主要是针对10人以下、只有一个Scrum团队的小型产品或项目的敏捷开发。对于小型团队来说&#xff0c;在Leangoo中创建一个单团队敏捷开发项目就可以很好地支持团队产品或项目的开发。适用场景适用于单个团队进行Scrum敏捷开发协作&#xff0c;Leangoo项目内也…

Linux - 磁盘存储管理 磁盘引入

# 我们要介绍下 磁盘管理&#xff0c; 那不妨先来看一张图来简单 引入 &#xff1a;这张图呢&#xff0c;是我们 Windows 上的磁盘管理的显示 。根据这幅图呢&#xff0c;提出一个问题 &#xff1a;>>> 这幅图磁盘管理所显示的内容&#xff0c;你能判断出 该电脑 有几…

【FMCW 04】测角-Angle FFT

在之前的文章中&#xff0c;我们已经详尽讨论过FMCW雷达测距和测速的原理&#xff0c;现在来讲最后一块内容&#xff0c;测角。测角对于硬件设备具有要求&#xff0c;即要求雷达具有多发多收结构&#xff0c;从而形成多个空间信道&#xff08;channel&#xff09;&#xff0c;我…

css选择器详解

简单选择器&#xff08;根据名称、id、类来选取元素&#xff09;组合器选择器&#xff08;根据它们之间的特定关系来选取元素&#xff09;伪类选择器&#xff08;根据特定状态选取元素&#xff09;伪元素选择器&#xff08;选取元素的一部分并设置其样式&#xff09;属性选择器…

第六讲:ambari-web 模块二次开发

上述图片为 Ambari 部署及操作 hdp 集群相关的部分界面截图。这些页面如果想调整的话,比如汉化,二次开发等,则可以修改 ambari-web 模块的源码来实现。 一、介绍 ambari-web 模块涉及到的界面有: HDP 集群部署向导已安装服务的仪表板、配置界面等主机列表及详细信息告警列…

【Opencv项目实战】图像的像素值反转

文章目录一、项目思路二、算法详解2.1、获取图像信息2.2、新建模板2.3、图像通道顺序三、项目实战&#xff1a;彩图的像素值反转&#xff08;方法一&#xff09;四、项目实战&#xff1a;彩图的像素值反转&#xff08;方法二&#xff09;五、项目实战&#xff1a;彩图转换为灰图…

Java中class文件的格式

常见的class文件格式如下图所示&#xff0c;下面我将对一下格式一一作出解释。 一、magic 该部分主要是对语言类型的规范&#xff0c;只有magic这个部分是CAFEBABE时才能被检测为Java语言&#xff0c;否则则不是。 二、minor version和major version minor version主要表示了…