博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spark SQL Join实现原理
阅读量:2428 次
发布时间:2019-05-10

本文共 2197 字,大约阅读时间需要 7 分钟。

1. 概要

Join是SQL语言中常用的操作,一般用于建立多表之间的连接关系。spark SQL有两类(三种)Join的实现,每种Join的实现方式都有各自不同的应用场景。

在这里插入图片描述

2. Hash Join

Hash Join实现原理

先来看看这样一条SQL语句:select * from order,item where item.id = order.i_id,参与join的两张表是order和item,join key分别是item.id以及order.i_id。现在假设join采用的是hash join算法,整个过程会经历三步:

  1. 确定Build Table以及Probe Table:这个概念比较重要,Build Table会被构建成以join key为key的hash table,而Probe Table使用join key在这张hash table表中寻找符合条件的行,然后进行join链接。Build表和Probe表是Spark决定的。通常情况下,小表会被作为Build Table,较大的表会被作为Probe Table。

  2. 构建Hash Table:依次读取Build Table(item)的数据,对于每一条数据根据Join Key(item.id)进行hash,hash到对应的bucket中(类似于HashMap的原理),最后会生成一张HashTable,HashTable会缓存在内存中,如果内存放不下会dump到磁盘中。

  3. 匹配:生成Hash Table后,在依次扫描Probe Table(order)的数据,使用相同的hash函数在Hash Table中寻找hash(join key)相同的值,如果匹配成功就将两者join在一起。

在这里插入图片描述

基本原理可以参考上图,这里有两个问题需要关注:

  1. hash join性能如何?很显然,hash join基本都只扫描两表一次,可以认为是O(a + b),较之最极端的是笛卡尔积运算O(a * b)。
  2. 为什么Build Table选择小表?道理很简单,因为构建Hash Table时,最好可以把数据全部加载到内存中,这也决定了hash join只适合于一张表较小的场景,如果是两个较大表的场景就不适用了。

上文的hash join是传统数据库中的单机join算法,为了尽可能利用分布式计算资源进行并行计算,提高总体效率,在分布式环境下需要经过一定的改造。hash join分布式实现有broadcast hash join和shuffle hash join两种方案:

Broadcast Hash Join

Broadcast Hash Join可以分为两步:

  1. broadcast阶段:将小表广播到所有的executor上,广播的算法有很多,最简单的是先发给driver,driver再统一分发给所有的executor,或者就是基于BT的p2p思路。
  2. hash join阶段:在每个executor上执行hash join,小表构建为hash table,大表的分区数据匹配hash table中的数据;

在这里插入图片描述

Broadcast Hash Join有以下几个条件:

  1. 被广播的表大小需要小于spark.sql.autoBroadcastJoinThreshold的值,默认是10M;
  2. 基表不能被广播,比如left outer join时只能广播右表。

Broadcast Hash Join的缺点也是比较明显的,即只能广播较小的表,否则数据的冗余传输会远大于shuffle的开销。另外被广播的表在每个executor上都会保存一份,这会对executor的内存造成一定的压力。

Shuffle Hash Join

Shuffle Hash Join分为两步:

  1. 对两张表分别按照join key进行shuffle,那么相同的key一定会落到相同的分区。
  2. 对应分区中的数据进行join,先将小表分区构建为一个hash表,然后根据大表中记录的join key的hash值拿来进行匹配,即每个节点单独执行hash算法。

在这里插入图片描述

3. Sort Merge Join

Hash Join方式只对于两张表中有一张是小表的情况适用,但当两个表都非常大时则不适合。这是因为join时生成的join key会非常大,不能将数据完全加载到内存中。为了应对大表join的场景,SparkSQL提供了一种全新的方案Sort Merge Join。

Sort Merge Join首先将两张表按照join key进行重新shuffle,保证join key值相同的记录会被分在相应的分区,分区后对每个分区内的数据进行排序,排序后再对相应的分区内的记录进行连接。可以看出,无论分区有多大,Sort Merge Join都不用把一侧的数据全部加载到内存中,因为两个序列都是有序的,此时从头遍历,碰到key相同的就输出,如果不同,左边小就继续取左边,反之取右边。

在这里插入图片描述

整个过程分为三个步骤:

  1. shuffle阶段:将两张大表根据join key进行重新分区。
  2. sort阶段:对单个分区节点的两表数据,分别进行排序;
  3. merge阶段:对排好序的两张分区表数据执行join操作。join操作很简单,分别遍历两个有序序列,碰到相同join key就merge输出,否则取更小一边,见下图示意:
    在这里插入图片描述

转载地址:http://wgcmb.baihongyu.com/

你可能感兴趣的文章
JavaScriptCore 全面解析 (上篇)
查看>>
移动周刊第 187 期:App 模块化实战经验总结
查看>>
以不一样的视角看物联网协议
查看>>
JavaScriptCore全面解析 (下篇)
查看>>
嵌入式操作系统与物联网演进之路
查看>>
苹果公司揭秘首批列入 Swift 源代码兼容性开源项目清单
查看>>
Python 玩转物联网之 Micropython GPIO IRQ 处理
查看>>
移动周刊第 188 期:Android 安全性要点与规范核心详析
查看>>
手机为基础的 IoT 布局已经失效,下一代操作系统是什么模样?
查看>>
无线传感器网络使用指南
查看>>
Unity 脚本优化的那些坑
查看>>
《近匠》专访机智云 CTO 刘琰——从 0 到 1 开启智能化硬件开发
查看>>
深度对话微软,解读 HoloLens 技术设计细节
查看>>
移动周刊第 191 期:如何看待 Kotlin 成为 Android 官方支持开发语言?
查看>>
物联网浪潮之下,前端工程师如何迎刃而上?
查看>>
从端到云——工业物联网项目全栈快速开发
查看>>
LoRa vs NB-IOT:哪个物联网标准更具优势?
查看>>
移动周刊第 205 期:Google 正式发布 ARCore 预览版、iOS 工程打包速度提升十倍的解决方案...
查看>>
八大 IoT 安全关键技术解析
查看>>
有钱 Python,没钱 PHP,编程语言也嫌贫爱富
查看>>