使用Spark groupByKey来重复删除RDD,这会导致大量的随机播放

时间:2017-11-19 03:38:44

标签: apache-spark mapreduce rdd

我有一个键值对RDD。 RDD包含一些具有重复键的元素,我想将原始RDD拆分为两个RDD:一个存储具有唯一键的元素,另一个存储其余元素。例如,

输入RDD(总共6个元素):

<k1,v1>, <k1,v2>, <k1,v3>, <k2,v4>, <k2,v5>, <k3,v6>

结果:

唯一键RDD(存储具有唯一键的元素;对于具有相同键的多个元素,接受任何元素):

<k1,v1>, <k2, v4>, <k3,v6>

重复密钥RDD(使用重复密钥存储其余元素):

<k1,v2>, <k1,v3>, <k2,v5>

在上面的例子中,唯一的RDD有3个元素,重复的RDD也有3个元素。

我尝试使用groupByKey()将具有相同键的元素组合在一起。对于每个键,都有一系列元素。但是,groupByKey()的性能不好,因为元素值的数据大小非常大,导致shuffle写入的数据量非常大。

所以我想知道是否有更好的解决方案。或者有没有办法减少使用groupByKey()时洗牌的数据量?

2 个答案:

答案 0 :(得分:2)

编辑:鉴于编辑中的新信息,我首先创建唯一的rdd,然后使用唯一的和原始的rdd创建重复的rdd:

reduceByKey

还有一些优化空间 在上面的解决方案中,将有2次shuffle(joininputRdd) 如果我们从一开始就通过密钥重新分配val inputRdd2 = inputRdd.partitionBy(new HashPartitioner(partitions=200) ) ,我们就不需要任何额外的随机播放 使用此代码应该会产生更好的性能:

val inputRdd: RDD[(K,V)] = ...

val countRdd: RDD[((K,V), Int)] = inputRDD
        .map((_, 1)) 
        .reduceByKey(_ + _)
        .cache

val uniqueRdd = countRdd.map(_._1)

val duplicateRdd = countRdd
         .filter(_._2>1)
         .flatMap { case(kv, count) => 
                  (1 to count-1).map(_ => kv)
   }

原始解决方案:

您可以尝试以下方法:
首先计算每对的出现次数,然后分成2个rdds

UITableViewCell

答案 1 :(得分:0)

请使用combineByKey导致在Map Task上使用组合器,从而减少混洗数据。

组合器逻辑取决于您的业务逻辑。

http://bytepadding.com/big-data/spark/groupby-vs-reducebykey/

There are multiple ways to reduce shuffle data. 
 1. Write less from Map task by use of combiner. 
 2. Send Aggregated serialized objects from Map to reduce. 
 3. Use combineInputFormts to enhance efficiency of combiners.