使用联合而不是加入apache spark更有效率,还是无关紧要?

时间:2015-05-30 17:38:37

标签: python performance join mapreduce apache-spark

最近我在apache spark集群上运行了一个工作,我打算在两个rdds上做一个内连接。然而,我认为,对于这个计算,我可以通过使用union,reduceByKey和filter来避免连接。但这基本上是连接已经在幕后做的事情吗?

说我在rdd中有对象具有以下结构:

  

{'key':'someKey','value':<某个正整数> }

然后为了避免我写的连接:

leftRDD = rdd1.map(lambda y: (y['key'], (1, y['value'], -1))
rightRDD = rdd2.map(lambda y: (y['key'], (0, -1, y['value']))
joinedRDD = (leftRDD + rightRDD) \
    .reduceByKey(lambda x,y: (max(x[0],y[0]), max(x[1],y[1]), max(x[2],y[2])) \
    .filter(lambda y: y[1][0] == 1)
现在,加入RDD会有效地产生与内部联接相同的结果,但增加的复杂性值得避免加入吗?

1 个答案:

答案 0 :(得分:1)

Pyspark加入的可扩展性往往很差 - 所以你在手动RDD操作中的预感很可能是好的。

特别是pyspark中的连接会丢失分区 - 因此不支持copartioned连接。

具体问题:你应该注意reduceByKey的语义:它输出相同的数据结构作为输入。根据您的代码,您可能会期待不同的东西。

有关reduceByKey的更多信息,请查看(PySpark) Nested lists after reduceByKey

<强>更新

原生scala版本在保留现有分区方面更为积极(不会导致完全混乱):

if (self.partitioner == Some(partitioner)) {
  self.mapPartitions(iter => {
    val context = TaskContext.get()
    new InterruptibleIterator(context, aggregator.combineValuesByKey(iter, context))
  }, preservesPartitioning = true)
} else {
  new ShuffledRDD[K, V, C](self, partitioner)
    .setSerializer(serializer)
    .setAggregator(aggregator)
    .setMapSideCombine(mapSideCombine)
}

相反,python版本总是引发一个shuffle:

    shuffled = locally_combined.partitionBy(numPartitions)

正是出于这个原因,我注意到了使用reduceByKey对pyspark的性能问题。

整体'答案'不是明确的是或否:我说它“可能是肯定的” - 取决于你如何编写自定义pyspark RDD代码而不仅仅是使用join() - 这总是会导致混乱。