reduceByKey与groupByKey之间的Spark差异与aggregateByKey vs combineByKey之间的差异

时间:2017-04-12 08:38:18

标签: apache-spark

任何人都可以解释reducebykey,groupbykey,aggregatebykey和combinebykey之间的区别吗?我已经阅读了有关这方面的文件,但无法理解确切的差异?

如果你能用例子来解释它,那就太好了。

6 个答案:

答案 0 :(得分:46)

<强> groupByKey:

语法:

sparkContext.textFile("hdfs://")
                    .flatMap(line => line.split(" ") )
                    .map(word => (word,1))
                    .groupByKey()
                    .map((x,y) => (x,sum(y)) )

groupByKey可能会导致磁盘无问题,因为数据通过网络发送并在reduce工作人员上收集。

<强> reduceByKey:

语法:

sparkContext.textFile("hdfs://")
                    .flatMap(line => line.split(" "))
                    .map(word => (word,1))
                    .reduceByKey((x,y)=> (x+y))

数据在每个分区合并,每个分区的一个密钥只有一个输出通过网络发送。     reduceByKey需要将所有值组合成另一个具有完全相同类型的值。

<强> aggregateByKey:

与reduceByKey相同,后者采用初始值。

3个参数作为输入 一世。初始值     II。组合逻辑     III。序列操作逻辑

*Example:* `

val keysWithValuesList = Array("foo=A", "foo=A", "foo=A", "foo=A", "foo=B", "bar=C", "bar=D", "bar=D")
    val data = sc.parallelize(keysWithValuesList)
    //Create key value pairs
    val kv = data.map(_.split("=")).map(v => (v(0), v(1))).cache()
    val initialCount = 0;
    val addToCounts = (n: Int, v: String) => n + 1
    val sumPartitionCounts = (p1: Int, p2: Int) => p1 + p2
    val countByKey = kv.aggregateByKey(initialCount)(addToCounts, sumPartitionCounts)

`

输出中: 按键总和结果汇总 吧 - &gt; 3 foo - &gt; 5

<强> combineByKey:

3个参数作为输入

  1. 初始值:与aggregateByKey不同,不需要总是传递常量,我们可以传递一个函数来返回一个新值。
  2. 合并功能
  3. 合并功能
  4. 实施例`

    val result = rdd.combineByKey(
                            (v) => (v,1),
                            ( (acc:(Int,Int),v) => acc._1 +v , acc._2 +1 ) ,
                            ( acc1:(Int,Int),acc2:(Int,Int) => (acc1._1+acc2._1) , (acc1._2+acc2._2)) 
                            ).map( { case (k,v) => (k,v._1/v._2.toDouble) })
            result.collect.foreach(println)
    

    `

    reduceByKey,aggregateByKey,combineByKey 首选 groupByKey

    参考: Avoid groupByKey

答案 1 :(得分:12)

  

虽然reducebykey和groupbykey都会产生相同的答案,但是   reduceByKey示例在大型数据集上运行得更好。那&#39; S   因为Spark知道它可以将输出与每个输出的公共密钥组合在一起   在洗牌之前进行分区。

     

另一方面,当调用groupByKey时 - 所有键值对   被拖着脚走走了。这是很多不确定的数据   通过网络传输。

有关详细信息,请查看以下链接

https://databricks.gitbooks.io/databricks-spark-knowledge-base/content/best_practices/prefer_reducebykey_over_groupbykey.html

答案 2 :(得分:11)

  • groupByKey()只是根据密钥对数据集进行分组。当RDD尚未分区时,它将导致数据混乱。
  • reduceByKey()就像分组+聚合一样。我们可以说reduceBykey()等于dataset.group(...)。reduce(...)。与groupByKey()不同,它会减少数据量。
  • aggregateByKey()在逻辑上与reduceByKey()相同,但它允许您以不同的类型返回结果。换句话说,它允许您将输入作为类型x,将聚合结果作为类型y。例如(1,2),(1,4)作为输入,(1,&#34; six&#34;)作为输出。它还需要零值,它将在每个键的开头应用。

注意:一个相似之处是它们都是广泛的操作。

答案 3 :(得分:4)

虽然它们都会获得相同的结果,但两种功能的性能存在显着差异。与reduceByKey()相比,groupByKey()可以更好地处理较大的数据集。

reduceByKey()中,在数据被混洗之前,将具有相同密钥的同一台机器上的对组合在一起(通过使用传递给reduceByKey()的函数)。然后再次调用该函数以减少每个分区的所有值,以产生一个最终结果。

groupByKey()中,所有键值对都会被改组。这是通过网络传输的大量不必要的数据。

答案 4 :(得分:2)

ReduceByKey reduceByKey(func, [numTasks]) -

组合数据,以便在每个分区中每个键至少应有一个值。 然后进行随机播放,并通过网络将其发送给某个特定的执行者,以执行某些操作,例如reduce。

GroupByKey - groupByKey([numTasks])

它不会合并密钥的值,但会直接发生洗牌过程 这里有大量数据发送到每个分区,几乎与初始数据相同。

每个键的值的合并都是在shuffle之后完成的。 这里有大量数据存储在最终工作节点上,从而导致内存不足问题。

AggregateByKey - aggregateByKey(zeroValue)(seqOp, combOp, [numTasks]) 它类似于reduceByKey,但您可以在执行聚合时提供初始值。

使用reduceByKey

    当我们运行大型数据集时,可以使用
  • reduceByKey

  • reduceByKey当输入和输出值类型相同时 超过aggregateByKey

此外,建议不要使用groupByKey而更喜欢reduceByKey。有关详细信息,请参阅here

您还可以参考此question来更详细地了解reduceByKeyaggregateByKey的内容。

答案 5 :(得分:0)

除了这4个,我们还有

foldByKey与reduceByKey相同,但具有用户定义的零值。

AggregateByKey使用3个参数作为输入,并使用2个函数进行合并(一个用于合并在同一分区上,另一个用于合并整个分区中的值。第一个参数是ZeroValue)

ReduceBykey仅接受1个参数,这是一个合并函数。

CombineByKey带有3个参数,所有3个都是函数。除了可以为ZeroValue提供功能外,其他功能与generateBykey类似。

GroupByKey不带任何参数,而是对所有内容进行分组。另外,跨分区的数据传输也会产生开销。