引言Join是SQL语句中的常用操作,良好的表结构能够将数据分散在不同的表中,使其符合某种范式,减少表冗余、更新容错等 。而建立表和表之间关系的最佳方式就是Join操作 。
对于Spark来说有3中Join的实现,每种Join对应着不同的应用场景:
- Broadcast Hash Join :适合一张较小的表和一张大表进行join
- Shuffle Hash Join : 适合一张小表和一张大表进行join,或者是两张小表之间的join
- Sort Merge Join :适合两张较大的表之间进行join
Hash Join
先来看看这样一条SQL语句:
2. 构建Hash Table:依次读取Build Table(item)的数据,对于每一行数据根据join key(item.id)进行hash,hash到对应的Bucket,生成hash table中的一条记录 。数据缓存在内存中,如果内存放不下需要dump到外存;
3. 探测:再依次扫描Probe Table(order)的数据,使用相同的hash函数映射Hash Table中的记录,映射成功之后再检查join条件(item.id = order.i_id),如果匹配成功就可以将两者join在一起 。
文章插图
基本流程可以参考上图,这里有两个小问题需要关注:
1. hash join性能如何?很显然,hash join基本都只扫描两表一次,可以认为o(a+b),较之最极端的笛卡尔集运算a*b,不知甩了多少条街;
2. 为什么Build Table选择小表?道理很简单,因为构建的Hash Table最好能全部加载在内存,效率最高;这也决定了hash join算法只适合至少一个小表的join场景,对于两个大表的join场景并不适用 。
上文说过,hash join是传统数据库中的单机join算法,在分布式环境下需要经过一定的分布式改造,说到底就是尽可能利用分布式计算资源进行并行化计算,提高总体效率 。hash join分布式改造一般有两种经典方案:
1. broadcast hash join:将其中一张小表广播分发到另一张大表所在的分区节点上,分别并发地与其上的分区记录进行hash join 。broadcast适用于小表很小,可以直接广播的场景;
2. shuffler hash join:一旦小表数据量较大,此时就不再适合进行广播分发 。这种情况下,可以根据join key相同必然分区相同的原理,将两张表分别按照join key进行重新组织分区,这样就可以将join分而治之,划分为很多小join,充分利用集群资源并行化 。
Broadcast Hash Join
大家知道,在数据库的常见模型中(比如星型模型或者雪花模型),表一般分为两种:事实表和维度表 。维度表一般指固定的、变动较少的表,例如联系人、物品种类等,一般数据有限 。而事实表一般记录流水,比如销售清单等,通常随着时间的增长不断膨胀 。
因为Join操作是对两个表中key值相同的记录进行连接,在SparkSQL中,对两个表做Join最直接的方式是先根据key分区,再在每个分区中把key值相同的记录拿出来做连接操作 。但这样就不可避免地涉及到shuffle,而shuffle在Spark中是比较耗时的操作,我们应该尽可能的设计Spark应用使其避免大量的shuffle 。
当维度表和事实表进行Join操作时,为了避免shuffle,我们可以将大小有限的维度表的全部数据分发到每个节点上,供事实表使用 。executor存储维度表的全部数据,一定程度上牺牲了空间,换取shuffle操作大量的耗时,这在SparkSQL中称作Broadcast Join,如下图所示:
文章插图
Table B是较小的表,黑色表示将其广播到每个executor节点上,Table A的每个partition会通过block manager取到Table A的数据 。根据每条记录的Join Key取到Table B中相对应的记录,根据Join Type进行操作 。这个过程比较简单,不做赘述 。
Broadcast Join的条件有以下几个:
1. 被广播的表需要小于
spark.sql.autoBroadcastJoinThreshold所配置的值,默认是10M (或者加了broadcast join的hint)
推荐阅读
- 蛇有牙齿吗,有几个牙齿 蛇的牙齿是什么样子的
- 应该是全网最全的JVM知识点总结
- 明日叶哪里有卖苗的,明日叶的功效
- 马鞭草茶能不能长期喝,大多是女性喝的
- 藿香清口茶在哪儿买,服用藿香正气水的注意事项
- PHP“垂死”十年
- 阿里云服务器是如何实现每台服务器都是公网IP的呢?
- 红茶桂花泡水喝的功效,桂花红茶的泡法步骤
- 怎么卸载找不到程序的流氓软件?
- 想验证安装的操作系统是否正版,可以这样找到Win10产品密钥