在Apache Spark中,为什么RDD.union不保留分区器?

时间:2015-04-30 20:49:43

标签: apache-spark partitioning hadoop-partitioning

众所周知,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以使用相同的分区键?

2 个答案:

答案 0 :(得分:40)

union是一种非常有效的操作,因为它不会移动任何数据。如果rdd1有10个分区而rdd2有20个分区,则rdd1.union(rdd2)将有30个分区:两个RDD的分区相互放置。这只是一个记账改变,没有洗牌。

但它必然会丢弃分区程序。为给定数量的分区构造分区器。生成的RDD具有许多与rdd1rdd2不同的分区。

在获得联盟之后,您可以运行repartition来对数据进行洗牌并按键进行组织。

上述情况有一个例外。如果rdd1rdd2具有相同的分区程序(具有相同数量的分区),则union的行为会有所不同。它将成对加入两个RDD的分区,为每个输入提供相同数量的分区。这可能涉及移动数据(如果分区不在同一位置)但不会涉及随机播放。在这种情况下,保留分区程序。 (此代码在PartitionerAwareUnionRDD.scala。)

答案 1 :(得分:1)

这不再成立。如果两个RDD具有完全相同的分区和分区数量,则union ed RDD也将具有相同的分区。这是在https://github.com/apache/spark/pull/4629中引入的,并已合并到Spark 1.3中。