Hive join(MapReduce)和Spark join

Hive的执行引擎默认是MapReduce,所以hive join实际是MapReduce join。当然如果是hive on spark模式,那么hive join就是spark join。

Hive join(MapReduce)

mr的join可以分成 common join(reduce阶段完成join)和map join(map阶段完成join)。

1.common join

如果不指定map join,或者不满足map join的条件,那么hive解析器默认进行common join操作,即在reduce阶段完成join。整个过程分为map,shuffle和reduce阶段。

  • map阶段:
    读取源表中的数据, 以 join on中的条件列作为key(如果有多个,可以进行组合),select,where中的列作为value,value中还会加上tag,标记这条数据属于哪个表。
  • shuffle阶段:
    对key进行hash,按照hash值送到不同的reduce中,相同hash值的数据送到相同的reduce中。
  • reduce阶段:
    reduce阶段完成join操作。reduce内部根据tag来判断数据是来自1表还是2表。在内部分成两组,做笛卡尔积。

实例如下:
SELECT a.id,a.dept,b.age FROM a join b ON (a.id = b.id)
在这里插入图片描述

2.map join

map join通常用于一个很小的表和一个大表join的场景,小表的大小由参数hive.mapjoin.smalltable.filesize来决定,默认25M。令hive.auto.convert.join=true,hive会在小表满足条件的时候自动转换为map join。

map端进行join的原理是broadcast join,把小表作为一个完成的驱动表进行join。通常情况下,一个表中的数据会分布在不同的map中进行处理,相同一个key对应的value可能存在不同的map中,这样就必须等到reduce中去连接。map join把小表全部读到内存中,发送到大表所在节点的内存中,在map阶段直接拿另外一个表的数据和内存中的表的数据做匹配。由于在map中进行了join操作,省去了reduce,运行的效率会高很多。

执行流程 :
在这里插入图片描述
(1)首先是Task A,它是一个Local Task(在客户端本地执行的task),负责扫描小表b的数据,将其转换成一个hashtable的数据结构,并写如到本地的文件中,之后将改文件加载到DistributeCache中。
(2)接下来是Task B,该任务是一个没有reduce的mr,启动map tasks扫描大表a,在map阶段,根据a的每一条记录去和DistributeCache中b表对应的HashTable关联,并直接输出结果。
(3)相关参数:

  • 小表自动选择Mapjoin:set hive.auto.convert.join=true;默认值:false。该参数为true时,Hive自动对左边的表统计量,若是小表就加入内存,即对小表使用Map join
  • 小表阀值:set hive.mapjoin.smalltable.filesize=25M;

Spark join

Spark将参与join的两张表抽象为流式遍历表(streamIter)和查找表(buildIter)。通常streamIter是大表,buildIter是小表,Spark根据join语句自动区分大小表。
在这里插入图片描述

1.broadcast join --小表对大表

将小表的数据分发到每个节点上,供大表使用。executor存储小表的全部数据,一定程度上牺牲了空间,换取shuffle操作大量的耗时。broadcast join的条件是:

  • (1)被广播的表需要小于 spark.sql.autoBroadcastJoinThreshold 所配置的值,默认是10M (或者加了broadcast join的hint)
  • (2)基表不能被广播,比如 left outer join 时,只能广播右表
    在这里插入图片描述

2.Shuffle Hash Join

因为被广播的表首先被collect到driver端,然后被冗余分发到每个executor上,所以当表较大时,对driver和executor端造成的压力比较大。
spark可以通过分区的形式将大批量的数据划分成n份较小的数据集进行并行计算。利用key相同必然分区相同的原理,sparkSQL将较大的表分而治之,先将表划分成n个分区,在对两个表中对应分区的数据分别进行hash join。
步骤:

  • 对两张表分别按照join keys进行重分区,即shuffle,目的是为了让有相同join keys的值分到对应的分区中。
  • 对对应分区中的数据进行join,此处先将小表分区构造成一张hash表,然后根据大表分区中记录的join keys,拿出来进行匹配。

条件是:

  • 分区的平均大小不超过spark.sql.autoBroadcastJoinThreshold所配置的值,默认是10M
  • 基表不能被广播,比如left outer join时,只能广播右表
  • 一侧的表要明显小于另外一侧,小的一侧将被广播(明显小于的定义为3倍小,此处为经验值)
  • 在这里插入图片描述

3.Sort Merge Join --大表对大表

将两张表按照join keys进行了重新shuffle,保证join keys值相同的记录会被分在相应的分区。分区后对每个分区内的数据进行排序,排序后再对相应的分区内的记录进行连接

因为两个序列都是有序的,从头遍历,碰到key相同的就输出;如果不同,左边小就继续取左边,反之取右边(即用即取即丢)
在这里插入图片描述

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值