Spark Join
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 前提条件:内表小能放进广播变量
相关文章:
Spark Join
Spark Join关联形式内关联外关联左外关联右外关联全外关联左半/逆关联关联机制NLJSMJHJ分发模式Join 选择等值 Join不等值 JoinJoin 按照关联形式(Join Types)划分 : 内关联、外关联、左关联、右关联 Join 按实现机制划分 : NLJ (Nested Loop Join) 、S…...
数字的转化规则?
数字的转化规则?js将字符串转换为数字的方式有哪些?1. 使用 parseInt()2. 使用 Number()3. 使用一元运算符 ()4.使用parseFloat()5. 使用 Math.floor()和Math.ceil()6.乘以数字7. 双波浪号 (~~) 运算符其它值到数字的转化规则1.Undefined 类型2.Null 类型…...
MySQL面试题-锁相关
目录 1.MySQL 锁的类型有哪些呢? 2.如何使用全局锁 3.如果要全库只读,为什么不使用set global readonlytrue的方式? 4.表级锁和行级锁有什么区别? 5.行级锁的使用有什么注意事项? 6.InnoDB 有哪几类行锁ÿ…...
Windows 终端编译 C代码
E:\My_SoftWare\Window gcc\windowbianji\mingw64\bin 此电脑--》属性--》系统--》高级系统设置--》环境变量--》Path--》新建--》粘贴路径 E:\My_SoftWare\Window gcc\windowbianji\mingw64\bin 打开命令终端 E: 回车 dir 显示所有文件 cd E:\My_SoftWare\Window gcc\C_co…...
SpringCloud:Feign的使用及配置
目录 Feign的使用及配置 1、Feign替代RestTemplate 2、使用Fegin步骤 3、自定义配置 4、Feign使用优化 5、Feign的最佳实践方式 Feign的使用及配置 1、Feign替代RestTemplate RestTemplate方式远程调用的问题 问题: 1、代码可读性差,编程体验不同…...
Parquet学习与使用之BloomFilter的应用
写在前面 最近在自己做自定义的OLAP系统,文件格式上用的是Parquet,但是发现Parquet各个API的示例代码很少。所以就打算把这个系列的文章写一下。 1. Parquet的Filter Parquet的过滤支持两大类,一类是基于Footer中的元数据进行RowGroup级别…...
95%置信区间计算-理解
机器学习中做多次试验后,需要计算指标的95%置信区间。 假设做了10次试验,计算得出的某指标分别为{x1,…,x10} 其均值为μ(x1...x10)/10\mu(x1 ... x10)/10μ(x1...x10)/10 方差σ∑(xi−μ)2/10\sigma\sum(x_i -\mu)^2/10σ∑(xi−μ)2/10 95%置信…...
深度学习pytorch实战三:VGG16图像分类篇自建数据集图像分类三类
1.自建数据集与划分训练集与测试集 2.模型相关知识 3.model.py——定义AlexNet网络模型 4.train.py——加载数据集并训练,训练集计算损失值loss,测试集计算accuracy,保存训练好的网络参数 5.predict.py——利用训练好的网络参数后,…...
2023年3月软考高项(信息系统项目管理师)报名走起!!!
信息系统项目管理师是全国计算机技术与软件专业技术资格(水平)考试(简称软考)项目之一,是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试,既属于国家职业资格考试,又是职称资…...
模电学习11 运算放大器学习入门
一、基本概念 运算放大器简称运放,是一种模拟电路实现的集成电路,可以对信号进行很高倍数的放大。一般有正相输入端、反相输入端、输出端口、正电源、负电源等接口。 运放可工作在饱和区、放大区,其中放大区极其陡峭,因为运放的放…...
spring学习3.5
Bean是什么 Spring里面的Bean就类似是定义的一个组件,而这个组件的作用就是实现某个功能的,这里所定义的Bean就相当于给了你一个更为简便的方法来调用这个组件去实现你要完成的功能。 IoC是什么 谁控制谁,控制什么? 传统Java SE程…...
名创优品:国内“触礁”,海外“提速”
在互联网经济十分发达、实体经济不太景气的时代背景下,自有品牌零售商代表名创优品却逆势而上,开始向着全球品牌类生活用品零售市场发起冲击,并凭借着“极致性价比大规模跑量”的独特优势在该领域取得了十分可观的成绩。 随着“Z时代”人群逐…...
Java学习笔记 --- Tomcat
一、JavaWeb 的概念 JavaWeb 是指,所有通过 Java 语言编写可以通过浏览器访问的程序的总称,叫 JavaWeb。 JavaWeb是基于请求和响应来开发的。请求是指客户端给服务器发送数据,叫请求 Request。 响应是指服务器给客户端回传数据,叫…...
面向对象设计模式:行为型模式之状态模式
文章目录一、引入二、状态模式2.1 Intent 意图2.2 Applicability 适用性2.3 类图2.4 Collaborations 合作2.5 Implementation 实现2.5 状态模式与策略模式的对比2.5 状态模式实例:糖果机2.6 状态模式实例:自行车升降档一、引入 State Diagram 状态图&am…...
【Python入门第二十五天】Python 作用域
变量仅在创建区域内可用。这称为作用域。 局部作用域 在函数内部创建的变量属于该函数的局部作用域,并且只能在该函数内部使用。 实例 在函数内部创建的变量在该函数内部可用: def myfunc():x 100print(x)myfunc()运行实例 100函数内部的函数 如…...
运行时数据区及程序计数器
运行时数据区 概述 运行时数据区,也就是下图这部分,它是在类加载完成后的阶段 当我们通过前面的:类的加载-> 验证 -> 准备 -> 解析 -> 初始化 这几个阶段完成后,就会用到执行引擎对我们的类进行使用,同时…...
手写操作系统+文件系统开源啦
哈喽,我是子牙,一个很卷的硬核男人。喜欢研究底层,聚焦做那些大家想学没地方学的课程:手写操作系统、手写虚拟机、手写模拟器、手写编程语言… 今年是我创业的第二年,已经做了两个课程:手写JVM、手写操作系…...
小众但意外觉得蛮好用的剪辑软件!纯良心分享
爱剪辑 有开屏广告,一共3个界面:首页、剪同款、我的。 剪辑、配乐、字幕、滤镜、加速、贴纸、配音等主流功能都有。 特色功能有剪裁视频、倒放视频、视频旋转、视频转换GIF、转场、提取音频、画中画等。 还可以拼接视频,不过不支持FLV等小众文…...
一文带你入门angular(下)
一、angular get数据请求 angular5.x之后get,post和服务器交互使用的是HttpClientModule模块。 1.首先要在app.module.ts中引入HttpClientModule并注入 import {HttpClientModule} from "angular/common/http" 注入: import:[ …...
2023-3-6刷题情况
分巧克力 题目描述 儿童节那天有 KKK 位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。 小明一共有 NNN 块巧克力,其中第 iii 块是 HiWiH_i \times W_iHiWi 的方格组成的长方形。 为了公平起见,小明需要从这 NNN 块巧克力中切出 KKK…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
[特殊字符] 手撸 Redis 互斥锁那些坑
📖 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作,想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁,也顺便跟 Redisson 的 RLock 机制对比了下,记录一波,别踩我踩过…...
