Spark SQL join操作详解

news2025/4/10 9:01:06

一、 数据准备

本文主要介绍 Spark SQL 的多表连接,需要预先准备测试数据。分别创建员工和部门的 Datafame,并注册为临时视图,代码如下:

val spark = SparkSession.builder().appName("aggregations").master("local[2]").getOrCreate()

val empDF = spark.read.json("/usr/file/json/emp.json")
empDF.createOrReplaceTempView("emp")

val deptDF = spark.read.json("/usr/file/json/dept.json")
deptDF.createOrReplaceTempView("dept")

两表的主要字段如下:

emp 员工表
 |-- ENAME: 员工姓名
 |-- DEPTNO: 部门编号
 |-- EMPNO: 员工编号
 |-- HIREDATE: 入职时间
 |-- JOB: 职务
 |-- MGR: 上级编号
 |-- SAL: 薪资
 |-- COMM: 奖金  
dept 部门表
 |-- DEPTNO: 部门编号
 |-- DNAME:  部门名称
 |-- LOC:    部门所在城市

注:emp.json,dept.json 可以在本仓库的resources 目录进行下载。

二、连接类型

Spark 中支持多种连接类型:

  • Inner Join : 内连接;
  • Full Outer Join : 全外连接;
  • Left Outer Join : 左外连接;
  • Right Outer Join : 右外连接;
  • Left Semi Join : 左半连接;
  • Left Anti Join : 左反连接;
  • Natural Join : 自然连接;
  • Cross (or Cartesian) Join : 交叉 (或笛卡尔) 连接。

其中内,外连接,笛卡尔积均与普通关系型数据库中的相同,如下图所示:

 

这里解释一下左半连接和左反连接,这两个连接等价于关系型数据库中的in和not in字句:

-- LEFT SEMI JOIN
SELECT * FROM emp LEFT SEMI JOIN dept ON emp.deptno = dept.deptno
-- 等价于如下的 IN 语句
SELECT * FROM emp WHERE deptno IN (SELECT deptno FROM dept)

-- LEFT ANTI JOIN
SELECT * FROM emp LEFT ANTI JOIN dept ON emp.deptno = dept.deptno
-- 等价于如下的 IN 语句
SELECT * FROM emp WHERE deptno NOT IN (SELECT deptno FROM dept)

所有连接类型的示例代码如下:

2.1 inner join

两表内接

// 1.定义连接表达式
val joinExpression = empDF.col("deptno") === deptDF.col("deptno")
// 2.连接查询 
empDF.join(deptDF,joinExpression).select("ename","dname").show()

// 等价 SQL 如下:
spark.sql("SELECT ename,dname FROM emp JOIN dept ON emp.deptno = dept.deptno").show()

2.2 full outer join

FULL OUTER JOIN 关键字返回左表(Websites)和右表(access_log)中所有的行。

empDF.join(deptDF, joinExpression, "outer").show()
spark.sql("SELECT * FROM emp FULL OUTER JOIN dept ON emp.deptno = dept.deptno").show()

2.3 left outer join

把左边表的数据全部取出来,而右边表的数据有相等的,显示出来,如果没有,显示NULL

empDF.join(deptDF, joinExpression, "left_outer").show()
spark.sql("SELECT * FROM emp LEFT OUTER JOIN dept ON emp.deptno = dept.deptno").show()

2.4 right outer join

把右边表的数据全部取出来,而左边表的数据有相等的,显示出来,如果没有,显示NULL

empDF.join(deptDF, joinExpression, "right_outer").show()
spark.sql("SELECT * FROM emp RIGHT OUTER JOIN dept ON emp.deptno = dept.deptno").show()

2.5 left_semi join

Semi Join,也叫半连接,是从分布式数据库中借鉴过来的方法。它的产生动机是:对于reduce side join,跨机器的数据传输量非常大,这成了join操作的一个瓶颈,如果能够在map端过滤掉不会参加join操作的数据,则可以大大节省网络IO,提升执行效率。

left_semi join子句中右边的表只能在 ON 子句中设置过滤条件,在 WHERE 子句、SELECT 子句或其他地方过滤都不行。

left_semi join和join对待右表中重复key的处理方式差异:因为 left semi join 是 in(keySet) 的关系,遇到右表重复记录,左表会跳过,而 join on 则会一直遍历。

最后的结果是这会造成性能,以及 join 结果上的差异。

left semi join 中最后 select 的结果只许出现左表,因为右表只有 join key 参与关联计算了,而 join on 默认是整个关系模型都参与计算了。

empDF.join(deptDF, joinExpression, "left_semi").show()
spark.sql("SELECT * FROM emp LEFT SEMI JOIN dept ON emp.deptno = dept.deptno").show()

2.6 left anti join

 left anti join的功能是在查询过程中,剔除左表中和右表有交集的部分

empDF.join(deptDF, joinExpression, "left_anti").show()
spark.sql("SELECT * FROM emp LEFT ANTI JOIN dept ON emp.deptno = dept.deptno").show()

2.7 cross join

CROSS JOIN 称为“交叉连接”或者“笛卡尔连接”。SQL CROSS JOIN 连接用于从两个或者多个连接表中返回记录集的笛卡尔积,即将左表的每一行与右表的每一行合并。

empDF.join(deptDF, joinExpression, "cross").show()
spark.sql("SELECT * FROM emp CROSS JOIN dept ON emp.deptno = dept.deptno").show()

2.8 natural join

自然连接是在两张表中寻找那些数据类型和列名都相同的字段,然后自动地将他们连接起来,并返回所有符合条件的结果。

spark.sql("SELECT * FROM emp NATURAL JOIN dept").show()

以下是一个自然连接的查询结果,程序自动推断出使用两张表都存在的 dept 列进行连接,其实际等价于:

spark.sql("SELECT * FROM emp JOIN dept ON emp.deptno = dept.deptno").show()

 

三、连接的执行

在对大表与大表之间进行连接操作时,通常都会触发shuffle join,两表的所有分区节点会进行ALL-to-ALL的通讯,这种查询通常比较昂贵,会对网络 IO 会造成比较大的负担。

 而对于大表和小表的连接操作,Spark 会在一定程度上进行优化,如果小表的数据量小于 Worker Node 的内存空间,Spark 会考虑将小表的数据广播到每一个 Worker Node,在每个工作节点内部执行连接计算,这可以降低网络的 IO,但会加大每个 Worker Node 的 CPU 负担。

是否采用广播方式进行 Join 取决于程序内部对小表的判断,如果想明确使用广播方式进行 Join,则可以在 DataFrame API 中使用 broadcast 方法指定需要广播的小表:

empDF.join(broadcast(deptDF), joinExpression).show()

 

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

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

相关文章

腾讯云服务器CVM标准型S5和S6区别性能评测

腾讯云服务器CVM标准型S5是次新一代云服务器规格,标准型S6是最新一代的云服务器,S6实例的CPU处理器主频性能要高于S5实例,同CPU内存配置下的标准型S6实例要比S5实例性能更好一些,但是目前标准型S5实例活动较多,云服务器…

【ChatGPT】预训练模型微调及其应用(ChatGLM-6B、duckduckgo_search、GPT在科研的应用等)

note instructGPT(基于提示学习的系列模型)——>GPT3.5(大规模预训练语言模型)——>ChatGPT模型(高质量数据标注反馈学习)。chatGPT三大技术:情景学习、思维链、自然指令学习。GPT4飞跃式…

ASEMI代理AD9833BRMZ-REEL原装ADI车规级AD9833BRMZ-REEL

编辑:ll ASEMI代理AD9833BRMZ-REEL原装ADI车规级AD9833BRMZ-REEL 型号:AD9833BRMZ-REEL 品牌:ADI/亚德诺 封装:MSOP-10 批号:2023 引脚数量:10 安装类型:表面贴装型 AD9833BRMZ-REEL汽车…

【都2023年了,还在问网络安全怎么入门】

前言 【都2023年了,还在问网络安全怎么入门】所以这一期就出一一个怎么学习网络安全的学习路线和方法,觉得有用的话点赞收藏下 首先咱们聊聊,学习网络安全方向通常会有哪些问题 1、打基础时间太长 学基础花费很长时间,光语言都有…

数据库系统概论--第二章课后习题

1.试述关系模型的三个组成部分。 答: 关系模型由关系数据结构、(关系操作集合)和(关系完整性约束)三部分组成。 2. 简述关系数据语言的特点和分类。 答:特点:1)集合操作方式; 2)高度非过程化; 3)集查询、DDL、DML、…

【C++STL精讲】string类的基本使用与常用接口

文章目录💐专栏导读💐文章导读🌷为什么要学习string类?🌷string类的基本使用🌷string类的常用接口🌺数据访问函数🌺容量相关函数🌺操作函数🌷迭代器与范围for…

“三步走”推动云原生转型之路

对于企业而言,如何平稳的从传统研发模式过渡到云原生时代,除了坚持结合云原生应用的特点,持续推动基础架构和应用架构的转型,还需要围绕“深度融合云技术能力、做厚业务基础能力、提升内建质量”等三个步骤,推进云原生…

SpringBoot 防护XSS攻击

目录 一、前言 1.1、XSS攻击流程 1.2、XSS攻击分类 1.3、攻击方式 二、解决方案 2.1、SPRINGBOOT XSS过滤插件(MICA-XSS) 2.2、MICA-XSS 配置 三、项目实战 3.1、项目环境 3.2、测试 3.2.1、测试GET请求 3.2.2、测试POST请求 3.2.3、测试POS…

优秀测试工程师必须掌握的关系型和非关系型数据库

写在前面 如果平时没有接触到数据库,或者接触数据库不够深入,那么这篇文章很适合你,这篇文章主要从关系性和非关系型数据库的适用场景出发,介绍了MySQL,MongoDB,Redis数据库的安装,备份和常用命令以及MySQL的性能测试…

CRM客户管理软件开发功能有哪些?

互联网技术的不断提高使得企业管理方式也发生了变化,企业CRM系统应用市场逐渐扩大,相关软件开发也引起越来越多商家企业的关注。因为企业CRM系统软件开发能够根据企业需求制作,帮助企业更好的追踪管理客户信息,实时更新并进行相关…

Amazon SageMaker简直就是机器学习平台的天花板

一、前言 最近参与了亚马逊云科技【云上探索实验】活动,通过Amazon SageMaker基于Stable Diffusion模型,非常简单快速搭建的第一个AIGC,一开始以为非常复杂,不懂动手操作,但实际上操作非常简单,没有想象中…

自己开发X86操作系统--LIUNUXOS

为了纪念Linus Torvalds创始开发的linux,我将自己开发的os命名为LIUNUXOS。 LIUNUXOS其原码分为两个部分,汇编工程和c/c工程,地址分别为: LIUNUXOS汇编工程原码地址 LIUNUXOS c/c工程原码地址 在这些工程中,源程序的…

Grafana获取URL地址中的json数据

官方教程:https://grafana.github.io/grafana-json-datasource/query-editor 文章目录配置Grafana的JSON API插件模拟URL路由配置插件展示json数据最终效果配置Grafana的JSON API插件 直接在界面中下载这个插件即可: 也可以使用命令安装: …

Python每日一练(20230411)

目录 1. 环形链表 🌟 2. 比较版本号 🌟🌟 3. 基本计算器 🌟🌟🌟 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏…

hbuildX运行uniapp项目到andiord真机调试

一、打开手机开发者模式 我的是小米手机,这里就介绍一下小米手机如何打开开发者模式。其他机型可以百度一下。 1、手机 桌面 找到【设置】点击打开 2、点击【我的设备】。 3、进入后上滑,看见【全部参数】的按钮,点击打开 4、进入后上滑…

内存管理、内存映射、mmap

内存管理 MMU:Memory Management Unit,内存管理单元,CPU中独立硬件,负责处理CPU的内存访问请求。虚拟地址到物理地址的转换(即虚拟内存管理)。 物理内存:真实存在的插在主板内存槽上的内存条&a…

springboot2.7.10整合neo4j -- 关系双向绑定(UNDIRECTED)

背景 依赖 springboot版本 2.7.10 本地neo4j安装的版本&#xff1a;4.4.19 依赖如下&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-neo4j</artifactId></dependency>sprin…

Java基础(七)面向对象编程(高级)

1. 关键字&#xff1a;static 回顾类中的实例变量&#xff08;即非static的成员变量&#xff09; class Circle{private double radius;public Circle(double radius){this.radiusradius;}public double findArea(){return Math.PI*radius*radius;} }创建两个Circle对象&…

NanoPC-T4 RK3399:(一)平台与框架介绍

概述:近几年工作一直围绕Rockchip进行,手里刚好有一块NanoPC-T4的板子,本专栏将围绕友善NanoPC-T4做一个深度探究和总结,涉及uboot,kernel,rootfs定制等知识点。 一:硬件介绍 NanoPC-T4不仅是世界上最小的全功能接口RK3399一体化主板, 而且是一款完全开源的高性能计算平…

Winnolin PK参数及BE分析

文章目录一、PK参数分析一、非房室模型分析方法操作1.创建数据模型2.建立字段映射3.选择模型参数4.设置参数单位&#xff08;Units&#xff09;5.选择输出参数6.执行&#xff0c;查看结果二、生物等效性分析1.创建数据模型2.建立字段映射3.执行查看结果一、PK参数分析 药代动力…