![](/img/trans.png)
[英]Apache Spark Transformations: groupByKey vs reduceByKey vs aggregateByKey
[英]Spark difference between reduceByKey vs groupByKey vs aggregateByKey vs combineByKey
誰能解釋 reducebykey、groupbykey、aggregatebykey 和 combinebykey 之間的區別? 我已閱讀有關此的文件,但無法理解確切的區別?
如果你能用例子來解釋它會很棒。
groupByKey:
句法:
sparkContext.textFile("hdfs://")
.flatMap(line => line.split(" ") )
.map(word => (word,1))
.groupByKey()
.map((x,y) => (x,sum(y)))
當數據通過網絡發送並在reduce worker 上收集時,groupByKey 可能會導致磁盤不足問題。
reduceByKey:
句法:
sparkContext.textFile("hdfs://")
.flatMap(line => line.split(" "))
.map(word => (word,1))
.reduceByKey((x,y)=> (x+y))
數據在每個分區合並,每個分區的一個鍵只有一個輸出通過網絡發送。 reduceByKey 需要將您的所有值組合成另一個具有完全相同類型的值。
聚合鍵:
與reduceByKey 相同,它采用初始值。
3 個參數作為輸入 i。 初始值 ii. 組合器邏輯 iii. 序列操作邏輯
例子:
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)
輸出:按鍵和結果欄聚合 -> 3 foo -> 5
組合鍵:
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
參考: 避免 groupByKey
groupByKey()
只是根據鍵對數據集進行分組。 當 RDD 尚未分區時,它會導致數據混洗。reduceByKey()
類似於分組 + 聚合。 我們可以說reduceByKey()
等價於dataset.group(...).reduce(...)。 與groupByKey()
不同,它會洗牌更少的數據。aggregateByKey()
在邏輯上與reduceByKey()
相同,但它允許您返回不同類型的結果。 換句話說,它允許您將輸入作為 x 類型並聚合結果作為 y 類型。 例如 (1,2),(1,4) 作為輸入,(1,"six") 作為輸出。 它還需要將在每個鍵的開頭應用的零值。注意:一個相似之處是它們都是廣泛的操作。
雖然 reducebykey 和 groupbykey 都會產生相同的答案,但 reduceByKey 示例在大型數據集上效果更好。 那是因為 Spark 知道它可以在混洗數據之前將輸出與每個分區上的公共鍵組合在一起。
另一方面,當調用 groupByKey 時 - 所有的鍵值對都被打亂了。 這是通過網絡傳輸的大量不必要的數據。
更詳細的檢查這個下面的鏈接
盡管它們都將獲取相同的結果,但是這兩個函數的性能存在顯着差異。 reduceByKey()
相比, groupByKey()
對更大的數據集效果更好。
在reduceByKey()
,在混洗數據之前,將同一台機器上具有相同鍵的對組合(通過使用傳遞給reduceByKey()
的函數reduceByKey()
。 然后再次調用該函數以減少每個分區的所有值以產生一個最終結果。
在groupByKey()
,所有的鍵值對都被打亂了。 這是通過網絡傳輸的大量不必要的數據。
ReduceByKey reduceByKey(func, [numTasks])
-
數據被合並,以便在每個分區中每個鍵至少有一個值。 然后 shuffle 發生,它通過網絡發送到某個特定的 executor 以執行一些操作,例如 reduce。
GroupByKey - groupByKey([numTasks])
它不合並鍵的值,而是直接進行混洗過程,這里大量數據被發送到每個分區,幾乎與初始數據相同。
並且每個鍵的值的合並是在 shuffle 之后完成的。 這里大量數據存儲在最終工作節點上,因此導致內存不足問題。
AggregateByKey aggregateByKey(zeroValue)(seqOp, combOp, [numTasks])
它類似於reduceByKey,但您可以在執行聚合時提供初始值。
使用reduceByKey
當我們在大型數據集上運行時可以使用reduceByKey
。
當輸入和輸出值類型在aggregateByKey
上是相同類型時reduceByKey
此外,它建議不要使用groupByKey
而更喜歡reduceByKey
。 有關詳細信息,請參閱此處。
您還可以參考此問題以更詳細地了解reduceByKey
和aggregateByKey
。
那么除了這4個之外,我們還有
foldByKey 與 reduceByKey 相同,但具有用戶定義的零值。
AggregateByKey 以 3 個參數作為輸入並使用 2 個函數進行合並(一個用於在同一分區上合並,另一個用於跨分區合並值。第一個參數是 ZeroValue)
然而
ReduceBykey 只接受 1 個參數,這是一個用於合並的函數。
CombineByKey 接受 3 個參數,所有 3 個都是函數。 與aggregateBykey 類似,只是它可以有一個針對ZeroValue 的函數。
GroupByKey 不接受任何參數並將所有內容分組。 此外,它是跨分區數據傳輸的開銷。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.