我正在寻找一种方法将结构发送到预先确定的分区,以便它们可以被另一个RDD使用
假设我有两个键值对的RDD
val a:RDD[(Int, Foo)]
val b:RDD[(Int, Foo)]
val aStructure = a.reduceByKey(//reduce into large data structure)
b.mapPartitions{
iter =>
val usefulItem = aStructure(samePartitionKey)
iter.map(//process iterator)
}
我怎样才能设置分区,以便我需要的特定数据结构将存在于mapPartition中,但我不会有额外的开销来发送所有值(如果我要制作一个广播变量)。
我曾经想过的一个想法是将对象存储在HDFS中,但我不确定这是不是一个次优的解决方案。
我目前正在探索的另一个想法是,是否有某种方法可以创建一个可以保存数据结构的自定义分区或分区程序(虽然这可能会变得太复杂并且会出现问题)
谢谢你的帮助!
编辑:
Pangea提出了一个非常好的观点,我应该提供一些更具体的内容。本质上我给出了SparseVectors的RDD和反向索引的RDD。倒排索引对象非常大。我希望在向量的RDD中进行MapPartition,我可以将每个向量与倒排索引进行比较。问题是我每个分区只需要一个倒排索引对象,并且进行连接会导致我拥有该索引的大量副本。
val vectors:RDD[(Int, SparseVector)]
val invertedIndexes:RDD[(Int, InvIndex)] = a.reduceByKey(generateInvertedIndex)
vectors:RDD.mapPartitions{
iter =>
val invIndex = invertedIndexes(samePartitionKey)
iter.map(invIndex.calculateSimilarity(_))
)
}
答案 0 :(得分:0)
Partitioner
是一个函数,给定一个泛型元素,它将返回它所属的分区。它还决定分区的数量。
有一种reduceByKey
形式将分区作为参数。
如果我正确理解您的问题,您希望在执行reduce时对数据进行分区。
参见示例:
// create example data
val a =sc.parallelize(List( (1,1),(1,2), (2,3),(2,4) ) )
// create simple sample partitioner - 2 partitions, one for odd
// one for even key.hashCode. You should put your partitioning logic here
val p = new Partitioner { def numPartitions: Int = 2; def getPartition(key:Any) = key.hashCode % 2 }
// your reduceByKey function. Sample: just add
val f = (a:Int,b:Int) => a + b
val rdd = a.reduceByKey(p, f)
// here your rdd will be partitioned the way you want with the number
// of partitions you want
rdd.partitions.size
res8: Int = 2
rdd.map() .. // go on with your processing