任何人都可以解释reducebykey,groupbykey,aggregatebykey和combinebykey之间的区别吗?我已经阅读了有关这方面的文件,但无法理解确切的差异?
如果你能用例子来解释它,那就太好了。
答案 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个参数作为输入
实施例`
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时 - 所有键值对 被拖着脚走走了。这是很多不确定的数据 通过网络传输。
有关详细信息,请查看以下链接
答案 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来更详细地了解reduceByKey
和aggregateByKey
的内容。
答案 5 :(得分:0)
除了这4个,我们还有
foldByKey与reduceByKey相同,但具有用户定义的零值。
AggregateByKey使用3个参数作为输入,并使用2个函数进行合并(一个用于合并在同一分区上,另一个用于合并整个分区中的值。第一个参数是ZeroValue)
而
ReduceBykey仅接受1个参数,这是一个合并函数。
CombineByKey带有3个参数,所有3个都是函数。除了可以为ZeroValue提供功能外,其他功能与generateBykey类似。
GroupByKey不带任何参数,而是对所有内容进行分组。另外,跨分区的数据传输也会产生开销。