Sparkのパーティショナーは誰もが知っているように、「ワイド」操作には大きなパフォーマンスの影響があるため、通常は操作でカスタマイズされます。次のコードを試してみました。
_val rdd1 =
sc.parallelize(1 to 50).keyBy(_ % 10)
.partitionBy(new HashPartitioner(10))
val rdd2 =
sc.parallelize(200 to 230).keyBy(_ % 13)
val cogrouped = rdd1.cogroup(rdd2)
println("cogrouped: " + cogrouped.partitioner)
val unioned = rdd1.union(rdd2)
println("union: " + unioned.partitioner)
_
デフォルトでは、cogroup()
は常にカスタマイズされたパーティショナーでRDDを生成しますが、union()
は生成しないため、常にデフォルトに戻ります。通常、PairRDDは最初の要素をパーティションキーとして使用する必要があると想定しているため、これは直観に反しています。 「強制」する方法はありますかSpark 2つのPairRDDをマージして同じパーティションキーを使用する方法はありますか?
union
はデータを移動しないため、非常に効率的な操作です。 _rdd1
_に10個のパーティションがあり、_rdd2
_に20個のパーティションがある場合、rdd1.union(rdd2)
には30個のパーティションがあります。これは単なる簿記の変更であり、変更はありません。
ただし、パーティショナーは必ず破棄されます。パーティショナーは、指定された数のパーティションに対して作成されます。結果のRDDには、_rdd1
_および_rdd2
_の両方とは異なるいくつかのパーティションがあります。
ユニオンを取得した後、repartition
を実行してデータをシャッフルし、キーで整理できます。
上記には1つの例外があります。 _rdd1
_と_rdd2
_のパーティショナーが同じ(パーティション数が同じ)場合、union
の動作は異なります。 2つのRDDのパーティションをペアで結合し、各入力と同じ数のパーティションを割り当てます。これにはデータの移動が含まれる場合があります(パーティションが同じ場所に配置されていない場合)が、シャッフルは含まれません。この場合、パーティショナーは保持されます。 (このコードは PartitionerAwareUnionRDD.scala にあります。)
これはもはや真実ではありません。 2つのRDDのパーティショナーとパーティション数がまったく同じ場合、union
ed RDDにも同じパーティションがあります。これは https://github.com/Apache/spark/pull/4629 で導入され、Spark 1.3。