【大数据】 对于Parir RDD转换操作中 combineByKey的理解
大部分内容来自于知乎博主
但其举的例子不是很恰当,后续查询简书博主 所讲的。
后面两幅图是我对上面两位博主知识的理解 所画
combineByKey[C]
(
createCombiner: V => C,
mergeValue: (C, V) => C,
mergeCombiners: (C, C) => C
)
-
第一个参数: createCombiner
-
作用就是初始化,将value 根据我们的需要做初始化,
- 比如将string类型的转化成int,或者是其他的操作。
-
我们用记号可以写成是 V => C,这里的V就是value,C是我们初始化之后的新值。
-
它会和value一起被当成新的pair传入第二个函数,
-
-
第二个参数: mergeValue
- 接受参数是(C, V)的二元组 。
- 我们要做的是定义这个二元组的合并,所以第二个函数可以写成(C, V) => C。
- 源码里的注释和网上的教程都是这么写的,但我觉得由于出现了两个C,可能会让人难以理解,我觉得可以写成(C, V) => D,比较好。
-
第三个参数: mergeCombiners
-
最后一个函数是将D进行合并,所以它可以写成是(D, D) => D。
-
有没有发现第二个函数和第三个函数都是用来合并的, 为什么我们要合并两次 ,它们之间的区别是什么?
- 其实这两次合并的逻辑大同小异,但是合并的范围不一样,
- 第一次合并是针对分区的,第二次合并是针对key的。
- 因为在spark当中数据可能不止存放在一个分区内,所以我们要合并两次,第一次先将分区内部的数据整合在一起,第二次再跨分区合并。
- 由于不同分区的数据可能相隔很远,所以会导致网络传输的时间过长,所以我们希望传输的数据尽量小,这才有了groupby两次的原因。
-
简书博主举例
val scores = Array(("Fred", 88), ("Fred", 95), ("Fred", 91), ("Wilma", 93), ("Wilma", 95), ("Wilma", 98))
求他们各自的平均成绩
思路是: 通过combineByKey函数把按照人分组 求出 他们的总分 和科目数 ,然后用map函数 除一下就完事