Spark RDD聚合/折叠操作业务场景

时间:2018-05-24 04:13:02

标签: scala apache-spark aggregate rdd

[编辑]实际上,我的问题是关于Spark RDD聚合操作的业务场景/要求,尤其是零值和RDD分区,但不是关于它如何在Spark中工作。对不起,感到困惑。

我正在学习各种Spark RDD计算。在研究Spark RDD聚合/折叠相关时,我无法想到聚合/折叠的业务场景。

例如,我将通过折叠计算RDD中的值的总和。

val myrdd1 = sc.parallelize(1 to 10, 2)
myrdd1.fold(1)((x,y) => x + y)

它返回58.

如果我们将分区号从2更改为4,则返回60.但我希望55。

我知道如果在制作myrdd1时没有给出分区号,火花会起什么作用。它将采用未知的默认分区号。返回值将是“不稳定的”。

所以我不知道为什么Spark有这种逻辑。真实的商业场景是否有这种要求?

2 个答案:

答案 0 :(得分:0)

fold聚合每个分区的数据,从第一个括号中的zero value开始。分区聚合结果最后与零值结合。

因此,对于2个分区,您正确收到了58个: (1 + 1 + 2 + 3 + 4 + 5)+(1 + 6 + 7 + 8 + 9 + 10)1

同样,对于4个分区,正确的结果是60: (1 + 1 + 2 + 3)+(1 + 4 + 5 + 6)+(1 + 7 + 8)+(1 + 9 + 10)1

对于现实世界的场景,这种类型的计算(分而治之)可能在您拥有可交换逻辑的任何地方都很有用,即当操作执行的顺序无关紧要时,如数学加法。因此,Spark只会在网络上移动聚合的部分结果,而不是像整个块一样移动。

如果您使用fold代替treeReduce,您对“收到55”的期望是:

"treeReduce" should "compute sum of numbers" in {
  val numbersRdd = sparkContext.parallelize(1 to 20, 10)
  val sumComputation = (v1: Int, v2: Int) => v1 + v2

  val treeSum = numbersRdd.treeReduce(sumComputation, 2)

  treeSum shouldEqual(210)
  val reducedSum = numbersRdd.reduce(sumComputation)
  reducedSum shouldEqual(treeSum)

}

前段时间我在RDD写了一篇关于树聚合的小帖子:http://www.waitingforcode.com/apache-spark/tree-aggregations-spark/read

答案 1 :(得分:0)

我认为你现在得到的结果是预期的,我会尝试解释它是如何运作的。

You have an `rdd` with 10 elements in two partition  
val myrdd1 = sc.parallelize(1 to 10, 2)

假设两个分区包含p1 = {1,2,3,4,5}p2 = {6,7,8,9,10}

现在根据文档,折叠在每个分区中运行 现在,您获得了(default value or zero value which is one in your case) +1+2+3+4+5 = 16(1 as zero value)+7+8+9+10 = 41

最后折叠那些(1 as zero value) 16 + 41 = 58

的人

同样,如果4分区fold在四个分区中运行,默认值为1,则将四个结果与另一个fold 1结合起来默认值和结果为60

  

汇总每个分区的元素,然后汇总所有分区的结果   分区,使用给定的关联函数和中性"零   值&#34 ;.函数op(t1,t2)允许修改t1并返回它   作为避免对象分配的结果值;但是,它不应该   修改t2。

     

这与为其实现的折叠操作略有不同   Scala等函数式语言中的非分布式集合。这个   折叠操作可以单独应用于分区,然后   将这些结果折叠成最终结果,而不是应用折叠   以某种定义的顺序顺序地对每个元素。对于功能   这不是可交换的,结果可能与折叠的结果不同   适用于非分布式集合。

总和零值应为0,这样可以得到55的正确结果。

希望这有帮助!