Spark自学之路(七)——数据分区

数据分区

       对数据集在节点间的分区控制。在分布式程序中,网络的通信代价是很大的,因此控制数据分布以获得最少的网络传输可以极大地提升整体性能,Spark可以控制RDD分区来减少网络通信开销。分区并不是对所有的应用都有好处,如果RDD只被扫描一次,没有分区的必要。只有数据集多次在注入连接这种基于键的操作中使用时,分区才会有帮助。

       Spark中所有的键值对RDD都可以进行分区。系统会根据一个针对键的函数对元素进行分组。尽管Spark没有给出显示控制每个键具体落在哪一个工作节点上的方法,但Spark可以确保同一组的键出现在同一个节点上。

例如:我们分析这样一个应用,他在内存中保存着一张很大的用户表——也就是由一个(UserID,UserInfo)对组成的RDD,其中UserInfo包含一个该用户所订阅的主题的列表。该应用会周期性地将这张表与一个小文件组合,这个小文件存着过去五分钟内发生的事件——(UserID,LinkInfo),过去五分钟内个网站用户访问的情况。我们可能需要对用户访问其未订阅主题的页面的情况进行统计。我们可以使用Spark的join操作来实现这个组合操作。

默认情况下,join操作会将两个数据集中的所有键的哈希值都找出来,将该哈希值相同的记录通过网络传到同一台机器上,然后在那台机器上对所有的键相同的记录进行连接操作。

每次执行join时都对userData表进行哈希值计算和跨节点数据混洗,虽然这些数据从来不会发生变化。为了解决这一问题,可以对userData表使用partitionBy() (不会改变原来的RDD)转换操作,将这张表转化为哈希分区。可以通过向partitionBy()传递一个spark.HashPartitioner对象来实现该操作。 

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

如果没有将partitionBy()转换操作的结果持久化,那么后面每次用到这个RDD时都会重复地对数据进行分区操作。不进行持久化操作会导致整个RDD谱系图重新求值,导致重复对数据进行分区以及跨节点的混洗。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SUISUIZHIBO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值