誰でもreducebykey、groupbykey、aggregatebykeyとcombinebykeyの違いを説明できますか?これに関するドキュメントを読みましたが、正確な違いを理解できませんでしたか?
例を使って説明できるといいですね。
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))
データは各パーティションで結合され、ネットワーク経由で送信する各パーティションの1つのキーに対して1つの出力のみが送信されます。 reduceByKeyでは、すべての値を完全に同じタイプの別の値に結合する必要がありました。
aggregateByKey:
reduceByKeyと同じで、初期値を取ります。
入力として3つのパラメーターi。初期値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)
`
ouput:キーサムによる集計結果バー-> 3 foo-> 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、combineByKeypreferred overgroupByKey
Reducebykeyとgroupbykeyの両方が同じ答えを生成しますが、reduceByKeyの例は大きなデータセットではるかにうまく機能します。 Sparkは、データをシャッフルする前に出力を各パーティションの共通キーと結合できることを知っているためです。
一方、groupByKeyを呼び出すと、すべてのキーと値のペアがシャッフルされます。これは、ネットワーク経由で転送される多くの不必要なデータです。
詳細については、以下のリンクをご覧ください
groupByKey()
は、キーに基づいてデータセットをグループ化するだけです。 RDDがまだパーティション化されていない場合、データがシャッフルされます。reduceByKey()
は、グループ化+集約のようなものです。 reduceBykey()はdataset.group(...)。reduce(...)と同等であると言えます。 groupByKey()
とは異なり、シャッフルするデータは少なくなります。aggregateByKey()
は、論理的にreduceByKey()と同じですが、異なるタイプで結果を返すことができます。つまり、入力をx型として、結果をy型として集計できます。たとえば、(1,2)、(1,4)を入力として、(1、 "six")を出力として。また、各キーの最初に適用されるzero-valueを取ります。注: 1つの類似点は、すべてが幅広い操作であるということです。
どちらも同じ結果を取得しますが、両方の関数のパフォーマンスには大きな違いがあります。 reduceByKey()
は、groupByKey()
と比較して、より大きなデータセットでより適切に機能します。
reduceByKey()
では、データがシャッフルされる前に、同じマシン上で同じキーを持つペアが(reduceByKey()
に渡される関数を使用して)結合されます。次に、関数が再度呼び出されて、各パーティションのすべての値が削減され、1つの最終結果が生成されます。
groupByKey()
では、すべてのキーと値のペアがシャッフルされます。これは、ネットワークを介して転送される多くの不要なデータです。
ReduceByKeyreduceByKey(func, [numTasks])
-
データは、各パーティションで各キーに少なくとも1つの値があるように結合されます。その後、シャッフルが発生し、ネットワーク経由で特定のエグゼキューターに送信され、reduceなどのアクションが実行されます。
GroupByKey-groupByKey([numTasks])
キーの値はマージされませんが、直接シャッフルプロセスが発生し、ここで多くのデータが初期パーティションとほぼ同じように各パーティションに送信されます。
そして、各キーの値のマージはシャッフル後に行われます。ここでは、多くのデータが最終的なワーカーノードに保存されるため、メモリ不足の問題が発生します。
AggregateByKey-aggregateByKey(zeroValue)(seqOp, combOp, [numTasks])
これはreduceByKeyと似ていますが、集計を実行するときに初期値を指定できます。
reduceByKey
の使用
reduceByKey
は、大きなデータセットで実行するときに使用できます。
reduceByKey
入力値と出力値の型がaggregateByKey
で同じ型の場合
さらに、groupByKey
を使用せず、reduceByKey
を優先することをお勧めします。詳細については、 こちら を参照してください。
この question を参照して、reduceByKey
およびaggregateByKey
の詳細を理解することもできます。
次に、これら4つとは別に、
foldByKey。reduceByKeyと同じですが、ユーザー定義のゼロ値を使用します。
AggregateByKeyは、入力として3つのパラメーターを受け取り、マージに2つの関数を使用します(同じパーティションでのマージと、パーティション全体で値をマージするための1つ。最初のパラメーターはZeroValueです)
一方、
ReduceBykeyは、マージのための関数である1つのパラメーターのみを取ります。
CombineByKeyは3つのパラメーターを取り、3つすべてが関数です。 aggregateBykeyに似ていますが、ZeroValueの関数を持つことができる点が異なります。
GroupByKeyはパラメーターを取らず、すべてをグループ化します。また、パーティション間でのデータ転送のオーバーヘッドです。