选项1:
val myRDD: RDD[MyType]
val grouped: RDD[(MyType, List[MyVector])] = myRDD.cartesian(myRDD)
.mapValues(List(_))
.reduceByKey( (x,y) => x:::y ) // or groupBy(_).mapValues(_.toList)
选项2:
val items: Array[MyType] = for (row <- myRDD.collect) yield row
val grouped: RDD[(MyType, List[MyVector])] = myRDD.map(x => (x, items.map(y => (x, y)).toList))
选项1似乎是自然的选择,但我发现的是即使对于非常小的集合,例如~500个元素,每个元素例如一百个双打的列表,reduceByKey(或groupBy) ,我也尝试过)映射到40000 ShuffleMapTasks,以每秒10次的速度完成。大约30分钟后,大约1/4完成后,作业因GC内存不足错误而失败。有没有办法确保笛卡尔积保留分区?有没有更有效的方法来处理reduce任务?我也尝试过不同的密钥(例如,Ints),但没有任何改进。
选项2对于我的特定情况非常快,因为该集合可以适合内存,但当然对于较大的集合来说它似乎是一个糟糕的选择。
我已经看过一些类似的问题,例如,
https://groups.google.com/forum/#!topic/spark-users/TZla5TnAMTU
Spark: what's the best strategy for joining a 2-tuple-key RDD with single-key RDD?
我确定其他人遇到过这个问题,我真的很感激任何指针!谢谢。
答案 0 :(得分:2)
你可以
要扩展3和我的评论,听起来像你有:
val myThings: RDD[MyType] = ...
你想要
val pairedWithOpResults: RDD[(MyType, MyType, OpResult]
所以我会做(伪代码):
val myThingsBroadcast = sc.broadcast(myThings.toArray())
myThings.flatMap(thingLeft => myThingsBroadcast.value.map(thingRight => (thingLeft, thingRight, myOp(thingLeft, thingRight)))
如果您想要执行某些groupBy,则需要清楚地解释您想要对每个结果组执行的操作。