Spark算子之combineByKey

学习combineByKey算子的时候,对它的3个参数很是疑惑。经过一番实际练习,算是基本弄明白了,因此记录一下。

combineByKey是针对不同partition进行操作的。它的第一个参数用于数据初始化(后面着重讲),第二个是针对一个partition的combine操作函数,第三个是在所有partition都combine完毕后,针对所有临时结果进行combine操作的函数。

关于数据初始化

之前有人说,初始化是对每个数据进行操作,这其实是错误的。应该是针对每个partition中,每个key下的第一个数据进行操作。这句话怎么理解呢?看代码:

val rdd1 = sc.parallelize(List(1,2,2,3,3,3,3,4,4,4,4,4), 2)
val rdd2 = rdd1.map((_, 1))
val rdd3 = rdd2.combineByKey(-_, (x:Int, y:Int) => x + y,
                            (x:Int, y:Int) => x + y)
rdd2.collect
rdd3.collect

以上代码的输出如下:

Array((1,1), (2,1), (2,1), (3,1), (3,1), (3,1), (3,1), (4,1), (4,1), (4,1), (4,1), (4,1))
Array((4,3), (2,0), (1,-1), (3,0))

在上述代码中,(1,1), (2,1), (2,1), (3,1), (3,1), (3,1) 被划分到第一个partition,(3,1), (4,1), (4,1), (4,1), (4,1), (4,1) 被划分到第二个。于是有如下操作:

(1, 1):由于只有1个,所以在值取负的情况下,自然输出(1, -1)
(2, 1):由于有2个,第一个取负,第二个不变,因此combine后为(2, 0)
(3, 1):partition1中有3个,参照上述规则,combine后为(3, 1),partition2中有1个,因此combine后为(3, -1)。在第二次combine时,不会有初始化操作,因此直接相加,结果为(3, 0)
(4, 1):过程同上,结果为(4, 3)

由此可以看出combineByKey算子的初始化执行流程,即只在partition的combine阶段有效,且仅对每个key下的第一个元素进行操作。

你可能感兴趣的:(Spark学习笔记)