join操作避免数据混洗的partitionBy()方法

我们经常需要把两张表进行join操作。
在join时,我们对数据集是如何分区的一无所知。
默认情况下,会把两个数据集中所有键的哈希值都求出来,将该哈希值相同的记录通过网络传到同一台机器上,然后在那台机器上对所有键相同的记录进行连接。
当出现特殊情况时,比如两张表里某张表非常大,并且这张表里的数据又没有变化过。那么每一次join都会去求所有哈希值,浪费了不少时间,每一次求出的哈希值都是一样的。如下图。
这里写图片描述

partitionBy()方法就是避免这种情况的。
可以在程序起始时就对userData表使用partitionBy()转化操作,将这张表转为哈希分区。
可以通过向partitionBy传递一个spark.HashPartitioner对象来实现该操作。

userData = sc.sequenceFile[UserID,UserInfo]("hdfs://...")
             .partitionBy(new HashPartitioner(100)) //构造100个分区
             .persist()

将userData分区后,spark会自动利用这一点。
当调用userData.join(events)时,spark就只会对events数据进行混洗操作,将events中特定的userID的记录发送到userData的对应分区所在的那台机器上,这样可以大大减少网络传输以及计算量。
这里写图片描述

要注意的是,partitionBy()是一个转化操作。因此它的返回值总是一个新的RDD,但它不会改变原来的RDD。所以一定要对partitionBy的结果进行持久化。不然每一次jion它都会重新分区,得不偿失。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值