我想将RDD划分为与我发现的不同键的数量相对应的多个分区(在这种情况下为3):
RDD:[(1,a), (1,b), (1,c), (2,d), (3,e), (3,f), (3,g), (3,h), (3,i)]
我现在要做的是具有相同键的元素将属于同一分区:
[(1,a), (1,b), (1,c)]
[(2,d)]
[(3,e), (3,f), (3,g), (3,h), (3,i)]
这就是我的分区方式
val partitionedRDD = rdd.partitionBy(new PointPartitioner(
rdd.keys.distinct().count().asInstanceOf[Int]))
这是PoinPartitioner类
class PointPartitioner(numParts: Int) extends org.apache.spark.Partitioner{
import org.apache.spark.Partitioner
override def numPartitions: Int = numParts
override def getPartition(key: Any): Int = {
key.hashCode % numPartitions
}
override def equals(other: Any): Boolean = other match
{
case dnp: PointPartitioner =>
dnp.numPartitions == numPartitions
case _ =>
false
}
}
但是,元素在各个分区之间是不平衡的。我想获得的是一个RDD分区,如下所示,其中所有分区都包含大致相同数量的元素,并遵守键的顺序:
[(1,a), (1,b), (1,c)]
[(2,d), (3,e), (3,f)]
[(3,g), (3,h), (3,i)]
我可以尝试什么?
答案 0 :(得分:2)
像这样分配分区
p1 [(1,a), (1,b), (1,c)]
p2 [(2,d), (3,e), (3,f)]
p3 [(3,g), (3,h), (3,i)]
表示您想将相同的分区键分配给不同的分区(对于3,它是p2或p3)。就像数学函数一样,同一参数不能有多个值(该值取决于什么?)。
您可以做的是在分区键中添加一些内容,这将导致有更多的存储桶(有效地将一组划分为较小的组)。但是,您(实际上)无法控制Spark如何将分区放置到节点上,因此您希望位于同一节点上的数据可以跨越多个节点。
这实际上归结为您想要执行的工作。我建议考虑要获得的结果,看看是否可以在合理的权衡下(如果确实需要)提出一些智能分区键。也许您可以按字母保留值,然后使用reduceByKey
而不是groupByKey
之类的操作来获得最终结果?