赞
踩
Spark Sql的Join和关系型数据库Sql的Join有很多相同点,比如inner join、left join、right join、full join,这是二者都有的概念,并且含义相同。
但是,Spark Sql是分布式执行、面对的是海量数据的特点,使得Spark Sql的Join体系要复杂的多。
Spark Sql的join类型分为:
和关系型数据库Sql没有区别。这四种类型定义了join的取数策略,不同join的结果不同。
基于Spark Sql面对的是海量数据,数据量是实现join必须要考虑的。Spark Sql提供三种实现方式:
简称为NLJ,对于两张要join的表,可以理解为两个集合。要找出满足join定义的数据,最直接简单的思路就是暴力循环。
使用两层循环,外循环针对左表,对左表的每一条记录,在内循环中逐条比对右表中的每一条记录,输出符合条件的记录,如果左表的条数为M,右表的条数为N,则算法复杂度为O(M*N)。
简称SMJ。这种算法需要两个表的数据是有序的,类似于归并排序,采用两个游标,分别指向两个表:
SMJ算法复杂度是O(M+N),比NLJ要优秀,但SMJ要求左右表数据有序。
Hash Join利用Hash值查找是否有匹配的数据。
首先加载右表全表,基于右表key建立Hash字典,字典key是基于某种Hash算法算出来的Hash值,value是源数据行。
遍历左表,对左表key进行hash,在前一步建立的字典查找是否有该hash值,有则进一步判断key是否相同。
Hash Join的效率最高,但需要提前将右表完全加载到内存中,对内存有较高要求。
Spark Sql是在分布式数据集上进行的计算,相同的key可能位于不同的partition,所以需要将相同的key通过网络收集到同一个partition,这就是著名的Shuffle过程。
Shuffle过程中的网络分发会导致性能大大降低,所以,在满足特定条件时,Spark Sql还提供了一种分发数据的方式,即BroadCast广播,Spark将右表通过广播分发到每个Executor,左表的数据无须分发,节省大量的网络IO。
SparkSql的三种实现算法和两种数据分发方式相结合,组合成了6种join。
Shuffle与BroadCast
Broadcast 需要满足一定条件,即右表的数据不能太大,Spark规定右表最大不能超过8G,因为Broadcast首先会将数据收集到Driver,然后分发到每一个Executor,所有对Driver和Executor的内存都有要求。
在满足条件时,Spark会首选BroadCast。
如果右表数据量很大,则不能通过Broadcast方式。
HJ/SMJ/NLJ
效率最高的是Hash Join,但HashJoin需要将右表全部加载到内存,容易导致OOM,所以Hash Join并不是Spark的首选,实际上默认并不开启Hash Join。
Spark的首选是SMJ,首先SMJ的效率并不低,且在数据量大时,其可以利用磁盘计算,稳定可靠,是Spark的首选。虽然其要求数据是有序的,但通常在ShuffleWrite过程中,会对数据排序。
最后才会选择NLJ,但NLJ也不是鸡肋,HJ和SMJ都限定于等值Join,非等值Join只能通过NLJ。
SMJ、NLJ其实挺难记,不过你打篮球的话,会意识到MJ不就是Micheal Jordan吗,或者Micheal Jackson也行。
LJ不就是LeBron James吗?
我就是这样记,不容易忘。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。