spark中dataframe解析_SparkSql 中 JOIN的实现

7a34a8b1fbf2e40c25951bf65c631be4.png

Join作为SQL中一个重要语法特性,几乎所有稍微复杂一点的数据分析场景都离不开Join,如今Spark SQL(Dataset/DataFrame)已经成为Spark应用程序开发的主流,作为开发者,我们有必要了解Join在Spark中是如何组织运行的。

SparkSQL总体流程介绍

在阐述Join实现之前,我们首先简单介绍SparkSQL的总体流程,一般地,我们有两种方式使用SparkSQL,一种是直接写sql语句,这个需要有元数据库支持,例如Hive等,另一种是通过Dataset/DataFrame编写Spark应用程序。如下图所示,sql语句被语法解析(SQL AST)成查询计划,或者我们通过Dataset/DataFrame提供的APIs组织成查询计划,查询计划分为两大类:逻辑计划和物理计划,这个阶段通常叫做逻辑计划,经过语法分析(Analyzer)、一系列查询优化(Optimizer)后得到优化后的逻辑计划,最后被映射成物理计划,转换成RDD执行。

57970ac99d8cf9332b0ab898f2143e6f.png

对于语法解析、语法分析以及查询优化,本文不做详细阐述,本文重点介绍Join的物理执行过程。

Join基本要素

如下图所示,Join大致包括三个要素:Join方式、Join条件以及过滤条件。其中过滤条件也可以通过AND语句放在Join条件中。

d8eb78ef26f09f6b7a77cc5109061b6a.png

Spark支持所有类型的Join,包括:

  • inner join
  • left outer join
  • right outer join
  • full outer join
  • left semi join
  • left anti join

下面分别阐述这几种Join的实现。

Join基本实现流程

总体上来说,Join的基本实现流程如下图所示,Spark将参与Join的两张表抽象为流式遍历表(streamIter)和查找表(buildIter),通常streamIter为大表,buildIter为小表,我们不用担心哪个表为streamIter,哪个表为buildIter,这个spark会根据join语句自动帮我们完成。

7ab360725dff4cf313afbe6e41e0e425.png

在实际计算时,spark会基于streamIter来遍历,每次取出streamIter中的一条记录rowA,根据Join条件计算keyA,然后根据该keyA去buildIter中查找所有满足Join条件(keyB==keyA)的记录rowBs,并将rowBs中每条记录分别与rowAjoin得到join后的记录,最后根据过滤条件得到最终join的记录。

从上述计算过程中不难发现,对于每条来自streamIter的记录,都要去buildIter中查找匹配的记录,所以buildIter一定要是查找性能较优的数据结构。spark提供了三种join实现:sort merge join、broadcast join以及hash join。

sort merge join实现

要让两条记录能join到一起,首先需要将具有相同key的记录在同一个分区,所以通常来说,需要做一次shuffle,map阶段根据join条件确定每条记录的key,基于该key做shuffle write,将可能join到一起的记录分到同一个分区中,这样在shuffle read阶段就可以将两个表中具有相同key的记录拉到同一个分区处理。前面我们也提到,对于buildIter一定要是查找性能较优的数据结构,通常我们能想到hash表,但是对于一张较大的表来说,不可能将所有记录全部放到hash表中,另外也可以对buildIter先排序,查找时按顺序查找,查找代价也是可以接受的,我们知道,spark shuffle阶段天然就支持排序,这个是非常好实现的,下面是sort merge join示意图。

33488964c3afe619d1fff550633ed79f.png

在shuffle read阶段,分别对streamIter和buildIter进行merge sort,在遍历streamIter时,对于每条记录,都采用顺序查找的方式从buildIter查找对应的记录,由于两个表都是排序的,每次处理完streamIter的一条记录后,对于streamIter的下一条记录,只需从buildIter中上一次查找结束的位置开始查找,所以说每次在buildIter中查找不必重头开始,整体上来说,查找性能还是较优的。

broadcast join实现

为了能具有相同key的记录分到同一个分区,我们通常是做shuffle,那么如果buildIter是一个非常小的表,那么其实就没有必要大动干戈做shuffle了,直接将buildIter广播到每个计算节点,然后将buildIter放到hash表中,如下图所示。

3264316050d71edb073b661279a22c32.png

从上图可以看到,不用做shuffle,可以直接在一个map中完成,通常这种join也称之为map join。那么问题来了,什么时候会用broadcast join实现呢?这个不用我们担心,spark sql自动帮我们完成,当buildIter的估计大小不超过参数spark.sql.autoBroadcastJoinThreshold设定的值(默认10M),那么就会自动采用broadcast join,否则采用sort merge join。

hash join实现

除了上面两种join实现方式外,spark还提供了hash join实现方式,在shuffle read阶段不对记录排序,反正来自两格表的具有相同key的记录会在同一个分区,只是在分区内不排序,将来自buildIter的记录放到hash表中,以便查找,如下图所示。

9ee6c2bb4e9226450ab220521d3a7db1.png

不难发现,要将来自buildIter的记录放到hash表中,那么每个分区来自buildIter的记录不能太大,否则就存不下,默认情况下hash join的实现是关闭状态,如果要使用hash join,必须满足以下四个条件:

  • buildIter总体估计大小超过spark.sql.autoBroadcastJoinThreshold设定的值,即不满足broadcast join条件
  • 开启尝试使用hash join的开关,spark.sql.join.preferSortMergeJoin=false
  • 每个分区的平均大小不超过spark.sql.autoBroadcastJoinThreshold设定的值,即shuffle read阶段每个分区来自buildIter的记录要能放到内存中
  • streamIter的大小是buildIter三倍以上

所以说,使用hash join的条件其实是很苛刻的,在大多数实际场景中,即使能使用hash join,但是使用sort merge join也不会比hash join差很多,所以尽量使用hash

下面我们分别阐述不同Join方式的实现流程。

inner join

inner join是一定要找到左右表中满足join条件的记录,我们在写sql语句或者使用DataFrmae时,可以不用关心哪个是左表,哪个是右表,在spark sql查询优化阶段,spark会自动将大表设为左表,即streamIter,将小表设为右表,即buildIter。这样对小表的查找相对更优。其基本实现流程如下图所示,在查找阶段,如果右表不存在满足join条件的记录,则跳过。

4b65c4964f276358e6e60fcf30db5b9d.png

left outer join

left outer join是以左表为准,在右表中查找匹配的记录,如果查找失败,则返回一个所有字段都为null的记录。我们在写sql语句或者使用DataFrmae时,一般让大表在左边,小表在右边。其基本实现流程如下图所示。

6bd6488b16ac81be24c74f853e1c3379.png

right outer join

right outer join是以右表为准,在左表中查找匹配的记录,如果查找失败,则返回一个所有字段都为null的记录。所以说,右表是streamIter,左表是buildIter,我们在写sql语句或者使用DataFrmae时,一般让大表在右边,小表在左边。其基本实现流程如下图所示。

a975ab6d3064022419fa72553135007a.png

full outer join

full outer join相对来说要复杂一点,总体上来看既要做left outer join,又要做right outer join,但是又不能简单地先left outer join,再right outer join,最后union得到最终结果,因为这样最终结果中就存在两份inner join的结果了。因为既然完成left outer join又要完成right outer join,所以full outer join仅采用sort merge join实现,左边和右表既要作为streamIter,又要作为buildIter,其基本实现流程如下图所示。

292d43572f4cfd812ea124502adc0abc.png

由于左表和右表已经排好序,首先分别顺序取出左表和右表中的一条记录,比较key,如果key相等,则joinrowA和rowB,并将rowA和rowB分别更新到左表和右表的下一条记录;如果keyA<keyB,则说明右表中没有与左表rowA对应的记录,那么joinrowA与nullRow,紧接着,rowA更新到左表的下一条记录;如果keyA>keyB,则说明左表中没有与右表rowB对应的记录,那么joinnullRow与rowB,紧接着,rowB更新到右表的下一条记录。如此循环遍历直到左表和右表的记录全部处理完。

left semi join

left semi join是以左表为准,在右表中查找匹配的记录,如果查找成功,则仅返回左边的记录,否则返回null,其基本实现流程如下图所示。

a660a5898bfd8c0e609e0ed5471fae15.png

left anti join

left anti join与left semi join相反,是以左表为准,在右表中查找匹配的记录,如果查找成功,则返回null,否则仅返回左边的记录,其基本实现流程如下图所示。

0463db82d3657a9d74e83e8979446a59.png

总结

Join是数据库查询中一个非常重要的语法特性,在数据库领域可以说是“得join者的天下”,SparkSQL作为一种分布式数据仓库系统,给我们提供了全面的join支持,并在内部实现上无声无息地做了很多优化,了解join的实现将有助于我们更深刻的了解我们的应用程序的运行轨迹。

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

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

相关文章

含枚举类型的函数声明_02Golang基础类型

基础类型命名Go语言中的函数名、变量名、常量名、类型名、语句标号和包名等所有的命名&#xff0c;都遵循一个简单的命名规则&#xff1a;一个名字必须以一个字母&#xff08;Unicode字母&#xff09;或下划线开头&#xff0c;后面可以跟任意数量的字母、数字或下划线。大写字母…

将xscj指定为当前数据库_通过网络连接数据库模式Hive的搭建过程详解

最近在搭建通过网络直接连接数据库模式的Hive时总是在启动的时候报各种错误&#xff0c;所以今天&#xff0c;我们来总结一下这种模式的Hive的搭建过程。【数据库安装】安装mysqlyum install mysql-server -y配置&#xff1a;启动mysql服务&#xff1a;service mysqld start设置…

游戏脚本代码大全_按键精灵】一个很好学的脚本

这【按键精灵】一个很好学的脚本命令名称&#xff1a;GetPixelColor 得到指定点颜色命令功能&#xff1a;得到指定位置的点的颜色命令参数&#xff1a;参数1 整数型&#xff0c;屏幕X坐标参数2 整数型&#xff0c;屏幕Y坐标返 回 值&#xff1a;【按键精灵】一个很好学的脚本字…

标记三维点_便携式3D扫描仪全自动三坐标测量机三维扫描设计扫描测量摄影

项目简介客户产品该客户的产品是铝铸件&#xff0c;铸件的很多位置没有太高的精度要求&#xff0c;但是铸件加工出来的孔位需要严格对上装配的位置&#xff0c;精加工的面要求却又特别高&#xff0c;并且孔位之间相距较远。客户的困难 由于产品要求较高&#xff0c;一般卡尺量具…

python画图显示不了中文_Python使用matplotlib绘图无法显示中文问题的解决方法

本文实例讲述了Python使用matplotlib绘图无法显示中文问题的解决方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a; 在python中&#xff0c;默认情况下是无法显示中文的&#xff0c;如下代码&#xff1a; import matplotlib.pyplot as plt # 定义文本框和箭头格式 d…

软件测试语句覆盖,软件测试中的语句覆盖,分支覆盖,条件覆盖以及路径覆盖...

我举一个简单的例子来解释一下语句覆盖&#xff0c;分支覆盖&#xff0c;条件覆盖以及路径覆盖的相关知识&#xff0c;如果有不对的地方&#xff0c;恳请各位同行指正&#xff1a;举例说明&#xff1a;if Atrue and Btrue then Action1if Ctrue or Dtrue then Action2这是一个很…

按钮点击没有反应_时控开关按键没反应怎么办?

当时市场上时控开关大体分为两种&#xff1a;按键式时控开关和蓝牙时控开关。按键式定时开关不用多做介绍&#xff0c;市场上已经存在很多年了&#xff0c;无论是校时、手动控制开关、设置定时时间&#xff0c;都需要手动接触按键进行调试控制&#xff0c;操作起来相对繁琐一些…

postman替换快捷键ctrl加什么_电脑截图快捷键ctrl加什么

无论我们使用电脑聊天&#xff0c;打游戏还是看视频&#xff0c;都不可避免会使用到截图的功能。下面小编来告诉大家windows自带的截图组合键吧。希望可以帮助到大家。www.aiwin10.com电脑截图快捷键是【ctrl】加【PrScrn】&#xff0c;使用这个组合键截屏&#xff0c;获得的是…

代码整理工具_整理了 11 个好用的代码质量审核和管理工具

点击上方“Python编程时光”&#xff0c;选择“加为星标”第一时间关注Python技术干货&#xff01;来源&#xff1a;云智时代https://www.toutiao.com/i6771334551873520131如今&#xff0c;代码质量分析和审核已成为每个企业的基本流程。随着开源代码库使用的增加&#xff0c;…

vue点击其它侧边栏收缩_企业微信聊天侧边栏功能怎么开启?聊天侧边栏有什么用?...

腾讯的企业微信上线以来一直在默默的优化更新&#xff0c;今年8月份悄悄上新了聊天侧边栏功能。作为一款主打移动端办公的软件&#xff0c;企业微信上线聊天侧边栏有什么用&#xff1f;聊天侧边栏是啥聊天侧边栏是企业微信的一个全新功能&#xff0c;为了方便公司成员更好的与客…

侧边栏配置_企业微信上线“聊天侧边栏”功能,可在外部会话时快捷使用应用...

点击上方“蓝色字体”&#xff0c;选择 “设为星标”关键讯息&#xff0c;D1时间送达&#xff01;8月7日消息&#xff0c;企业微信发布全新2.8.10版本&#xff0c;新增“聊天侧边栏”功能&#xff0c;且同时支持PC端与移动端。成员在外部会话中&#xff0c;可通过侧边栏使用应用…

vlc文件服务器局域网,vlc流媒体服务器配置

vlc流媒体服务器配置 内容精选换一换本节操作以Windows Server 2012操作系统的弹性云服务器为例介绍实现多用户登录的操作步骤。Windows server2012服务器默认能够支持两个用户同时远程登录&#xff0c;而通过配置远程桌面会话主机和远程桌面授权&#xff0c;即可实现多用户远程…

db2导入发生错误显示不是绝对路径_python编程常见错误总结

对于python初学者,在编程过程中常犯的错误及解决办法进行汇总和解决。勇哥希望编写此文能帮到大家。下边是勇哥结合例子给大家现身说法&#xff1a; 第一例&#xff1a;缩进错误(IndentationError)图1python对缩进很敏感&#xff0c;python用缩进来划分语句块&#xff0c;对于同…

服务器通电显示黄灯,服务器内存亮黄灯

服务器内存亮黄灯 内容精选换一换本文介绍了裸金属服务器BMS产品新特性和对应的文档动态&#xff0c;新特性将在各个区域(Region)陆续发布&#xff0c;欢迎体验。当您购买的云服务器规格无法满足业务需要时&#xff0c;可参考本章节变更规格&#xff0c;升级vCPU、内存。对于部…

mybatis mysql 调用存储过程 多个返回值_图解MyBatis的SQL执行流程(干货)

前言MyBatis可能很多人都一直在用&#xff0c;但是MyBatis的SQL执行流程可能并不是所有人都清楚了&#xff0c;那么既然进来了&#xff0c;通读本文你将收获如下&#xff1a;1、Mapper接口和映射文件是如何进行绑定的2、MyBatis中SQL语句的执行流程3、自定义MyBatis中的参数设置…

华为手机显示解析服务器返回错误,ajax服务器返回错误

ajax服务器返回错误 内容精选换一换查询指定备份策略下的标签信息。URI格式GET /v2/{project_id}/backuppolicy/{policy_id}/tagsGET /v2/{project_id}/backuppolicy/{policy_id}/tags参数说明参数是否必选描述project_id是项目IDpolicy_id是策略ID请求示例GET /查询所有备份策…

pandas 对某一行标准化_Python中的神器Pandas,但是有人说Pandas慢...

如果你从事大数据工作&#xff0c;用Python的Pandas库时会发现很多惊喜。Pandas在数据科学和分析领域扮演越来越重要的角色&#xff0c;尤其是对于从Excel和VBA转向Python的用户。所以&#xff0c;对于数据科学家&#xff0c;数据分析师&#xff0c;数据工程师&#xff0c;Pand…

罗盘时钟编码代码_安全研究 | 利用macOS Dock实现代码的持久化执行

背景介绍近期&#xff0c;我一直在研究macOS上的一些持久化技术&#xff0c;尤其是如何利用低等级用户权限来修改文件以影响用户交互。对于macOS终端用户来说&#xff0c;交互最频繁的当属Dock了。在我的研究过程中&#xff0c;我发现了一个plist文件&#xff0c;它可以控制App…

xpress-mp优化实例精选_量化研究每周精选-20170711

本周为大家精选了5项机器学习/深度学习在量化投资中的相关资源&#xff0c;机器学习/深度学习是偏实践性学科&#xff0c;只有不断实践才能有所收获&#xff0c;纸上得来终觉浅&#xff0c;绝知此事要躬行&#xff01;BigQuant拥有海量的数据和主流开源框架&#xff0c;附能每一…

mac 删除分区 command r 选择网络_Mac使用必看基础篇,Mac快捷键大全,mac新手入门指南...

你是Mac新手吗&#xff1f;你对使用Mac电脑有疑问吗&#xff1f;你还不知道mac有哪些快捷键吗&#xff1f;别着急&#xff0c;来看看小编给大家准备的Mac使用必看基础篇——Mac快捷键大全&#xff0c;对于新手用户很有帮助哦&#xff01;&#xff01;一、开机相关命令快捷键C:从…