鉴于以下RDD:
val vectors = RDD [String, Int] = ((k1,v1),(k1,v2),(k2,v3),...)
其中键出现两次(k1)或一次(k2),但不会超过。我想得到:
val uniqVectors = RDD[String, Int] = ((k1, v1*v2), (k2, v3), ...)
一种方法是使用reduceByKey:
val uniqVectors = vectors.reduceByKey((a,b) => a*b)
但是,对于具有7B元素的数组来说,它太慢了。 在这个具体案例中有没有更快的方法?
答案 0 :(得分:0)
这里花费时间(可能)正在改变数据:当你想要将两个或多个记录组合在一起时,它们必须位于同一个分区中,因此Spark必须首先 shuffle 记录这样所有具有相同密钥的记录都在一个分区中。
现在,即使每个密钥最多有两个记录,也必须进行此随机播放,除非您能以某种方式保证每个密钥已包含在单个分区中 - 例如,如果你从HDFS加载这个RDD,你知道每个键都在一个文件部分开始。在那种(不太可能)的情况下,您可以使用mapPartitions
分别在每个分区上自行执行分组,从而节省随机播放:
vectors.mapPartitions(
iter => iter.toList.groupBy(_._1).map { case (k, list) => (k, list.map(_._2).reduce(_ * _)) }.iterator,
preservesPartitioning = true)
顺便说一下,对于每个键的最大重复次数为2的情况,这一点都不是特别的。