web-dev-qa-db-ja.com

Apache Sparkで、RDD.unionがパーティショナーを保持しないのはなぜですか?

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をマージして同じパーティションキーを使用する方法はありますか?

24
tribbloid

unionはデータを移動しないため、非常に効率的な操作です。 _rdd1_に10個のパーティションがあり、_rdd2_に20個のパーティションがある場合、rdd1.union(rdd2)には30個のパーティションがあります。これは単なる簿記の変更であり、変更はありません。

ただし、パーティショナーは必ず破棄されます。パーティショナーは、指定された数のパーティションに対して作成されます。結果のRDDには、_rdd1_および_rdd2_の両方とは異なるいくつかのパーティションがあります。

ユニオンを取得した後、repartitionを実行してデータをシャッフルし、キーで整理できます。


上記には1つの例外があります。 _rdd1_と_rdd2_のパーティショナーが同じ(パーティション数が同じ)場合、unionの動作は異なります。 2つのRDDのパーティションをペアで結合し、各入力と同じ数のパーティションを割り当てます。これにはデータの移動が含まれる場合があります(パーティションが同じ場所に配置されていない場合)が、シャッフルは含まれません。この場合、パーティショナーは保持されます。 (このコードは PartitionerAwareUnionRDD.scala にあります。)

42
Daniel Darabos

これはもはや真実ではありません。 2つのRDDのパーティショナーとパーティション数がまったく同じ場合、unioned RDDにも同じパーティションがあります。これは https://github.com/Apache/spark/pull/4629 で導入され、Spark 1.3。

2
Joel Croteau