最近我在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会有效地产生与内部联接相同的结果,但增加的复杂性值得避免加入吗?
答案 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() - 这总是会导致混乱。