【Spark系列2】reduceByKey和groupByKey区别与用法

原创 2015年11月21日 15:47:00

在spark中,我们知道一切的操作都是基于RDD的。在使用中,RDD有一种非常特殊也是非常实用的format——pair RDD,即RDD的每一行是(key, value)的格式。这种格式很像Python的字典类型,便于针对key进行一些处理。


针对pair RDD这样的特殊形式,spark中定义了许多方便的操作,今天主要介绍一下reduceByKey和groupByKey,因为在接下来讲解《在spark中如何实现SQL中的group_concat功能?》时会用到这两个operations。


首先,看一看spark官网[1]是怎么解释的:

reduceByKey(func, numPartitions=None)

Merge the values for each key using an associative reduce function. This will also perform the merginglocally on each mapper before sending results to a reducer, similarly to a “combiner” in MapReduce. Output will be hash-partitioned with numPartitions partitions, or the default parallelism level if numPartitions is not specified.

也就是,reduceByKey用于对每个key对应的多个value进行merge操作,最重要的是它能够在本地先进行merge操作,并且merge操作可以通过函数自定义。

groupByKey(numPartitions=None)

Group the values for each key in the RDD into a single sequence. Hash-partitions the resulting RDD with numPartitions partitions. Note: If you are grouping in order to perform an aggregation (such as a sum or average) over each key, using reduceByKey or aggregateByKey will provide much better performance.

也就是,groupByKey也是对每个key进行操作,但只生成一个sequence。需要特别注意“Note”中的话,它告诉我们:如果需要对sequence进行aggregation操作(注意,groupByKey本身不能自定义操作函数),那么,选择reduceByKey/aggregateByKey更好。这是因为groupByKey不能自定义函数,我们需要先用groupByKey生成RDD,然后才能对此RDD通过map进行自定义函数操作。


为了更好的理解上面这段话,下面我们使用两种不同的方式去计算单词的个数[2]:

val words = Array("one", "two", "two", "three", "three", "three")

val wordPairsRDD = sc.parallelize(words).map(word => (word, 1))

val wordCountsWithReduce = wordPairsRDD.reduceByKey(_ + _)

val wordCountsWithGroup = wordPairsRDD.groupByKey().map(t => (t._1, t._2.sum))
上面得到的wordCountsWithReduce和wordCountsWithGroup是完全一样的,但是,它们的内部运算过程是不同的。


(1)当采用reduceByKeyt时,Spark可以在每个分区移动数据之前将待输出数据与一个共用的key结合。借助下图可以理解在reduceByKey里究竟发生了什么。 注意在数据对被搬移前同一机器上同样的key是怎样被组合的(reduceByKey中的lamdba函数)。然后lamdba函数在每个区上被再次调用来将所有值reduce成一个最终结果。整个过程如下:



(2)当采用groupByKey时,由于它不接收函数,spark只能先将所有的键值对(key-value pair)都移动,这样的后果是集群节点之间的开销很大,导致传输延时。整个过程如下:


因此,在对大数据进行复杂计算时,reduceByKey优于groupByKey

另外,如果仅仅是group处理,那么以下函数应该优先于 groupByKey
  (1)、combineByKey 组合数据,但是组合之后的数据类型与输入时值的类型不一样。
  (2)、foldByKey合并每一个 key 的所有值,在级联函数和“零值”中使用。


最后,对reduceByKey中的func做一些介绍:

如果是用Python写的spark,那么有一个库非常实用:operator[3],其中可以用的函数包括:大小比较函数,逻辑操作函数,数学运算函数,序列操作函数等等。这些函数可以直接通过“from operator import *”进行调用,直接把函数名作为参数传递给reduceByKey即可。如下:

<span style="font-size:14px;">from operator import add
rdd = sc.parallelize([("a", 1), ("b", 1), ("a", 1)])
sorted(rdd.reduceByKey(add).collect())

[('a', 2), ('b', 1)]</span>



参考:

[1] http://spark.apache.org/docs/latest/api/python/pyspark.html?highlight=reducebykey#pyspark.RDD.reduceByKey

[2] http://www.iteblog.com/archives/1357

[3] https://docs.python.org/2/library/operator.html

版权声明:本文为博主原创文章,未经博主允许不得转载。

spark RDD算子(七)之键值对分组操作 groupByKey,cogroup

groupByKeydef groupByKey(): RDD[(K, Iterable[V])]def groupByKey(numPartitions: Int): RDD[(K, Iterabl...
  • T1DMzks
  • T1DMzks
  • 2017年04月23日 21:44
  • 2963

Spark API 详解/大白话解释 之 groupBy、groupByKey

groupBy(function) function返回key,传入的RDD的各个元素根据这个key进行分组val a = sc.parallelize(1 to 9, 3) a.groupBy(x...
  • guotong1988
  • guotong1988
  • 2016年01月21日 18:07
  • 15168

Spark groupbykey和cogroup使用示例

groupByKey groupByKey([numTasks])是数据分组操作,在一个由(K,V)对组成的数据集上调用,返回一个(K,Seq[V])对的数据集。 val rdd0 = sc.pa...
  • u013063153
  • u013063153
  • 2017年06月27日 13:08
  • 787

Spark源码之reduceByKey与GroupByKey

Spark中针对键值对类型的RDD做各种操作比较常用的两个方法就是ReduceByKey与GroupByKey方法,下面从源码里面看看ReduceByKey与GroupByKey方法的使用以及内部逻辑...
  • do_yourself_go_on
  • do_yourself_go_on
  • 2017年07月26日 09:53
  • 394

Spark编程之基本的RDD算子之cogroup,groupBy,groupByKey

Spark编程之基本的RDD算子之cogroup,groupBy,groupByKey 1) cogroup [Pair], groupWith [Pair] 首先来看一下它的api。def cogr...
  • stevekangpei
  • stevekangpei
  • 2017年07月24日 14:50
  • 903

groupByKey reduceByKey

Spark算子:RDD键值转换操作(3)–groupByKey、reduceByKey、reduceByKeyLocally1.groupByKeydef groupByKey():RDD[( K, ...
  • power0405hf
  • power0405hf
  • 2015年12月03日 10:36
  • 905

groupByKey 和reduceByKey 的区别:

他们都是要经过shuffle的,groupByKey在方法shuffle之间不会合并原样进行shuffle,。reduceByKey进行shuffle之前会先做合并,这样就减少了shuffle的io传...
  • ZMC921
  • ZMC921
  • 2017年07月14日 10:53
  • 553

spark transform系列__groupByKey

这个操作的作用根据相同的key的所有的value存储到一个集合中的一个玩意. def groupByKey(): RDD[(K, Iterable[V])] = self.withScope { ...
  • u014393917
  • u014393917
  • 2016年01月28日 11:35
  • 844

Spark使用小结:Java版的GroupByKey示例

Spark Java版的GroupByKey示例 感觉reduceByKey只能完成一些满足交换率,结合律的运算,如果想把某些数据聚合到一些做一些操作,得换groupbykey 比如下面:我想把相...
  • fanzitao
  • fanzitao
  • 2016年04月22日 20:44
  • 3052

避免使用GroupByKey

有两种方法实现wordcount,一种是使用reduceByKey,另一种是使用groupByKey。 val words = Array("one", "two", "two", "three",...
  • sdujava2011
  • sdujava2011
  • 2016年01月28日 10:41
  • 691
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【Spark系列2】reduceByKey和groupByKey区别与用法
举报原因:
原因补充:

(最多只允许输入30个字)