Apache spark 使用PartitionBy按键拆分和高效计算RDD组

Apache spark 使用PartitionBy按键拆分和高效计算RDD组,apache-spark,rdd,Apache Spark,Rdd,我已经实现了一个解决方案,通过键对组RDD[K,V],并使用partitionBy和Partitioner根据每个组(K,RDD[V])计算数据。然而,我不确定它是否真的有效,我想听听你的观点 下面是一个示例案例:根据[K:Int,V:Int]列表,计算K每组的Vs平均值,知道它应该分布,并且V值可能非常大。这将使: List[K, V] => (K, mean(V)) 简单分区器类: class MyPartitioner(maxKey: Int) extends Partitione

我已经实现了一个解决方案,通过键对组
RDD[K,V]
,并使用
partitionBy
Partitioner
根据每个组
(K,RDD[V])
计算数据。然而,我不确定它是否真的有效,我想听听你的观点

下面是一个示例案例:根据
[K:Int,V:Int]
列表,计算
K
每组的
V
s平均值,知道它应该分布,并且
V
值可能非常大。这将使:

List[K, V] => (K, mean(V))
简单分区器类:

class MyPartitioner(maxKey: Int) extends Partitioner {

    def numPartitions = maxKey

    def getPartition(key: Any): Int = key match {
      case i: Int if i < maxKey => i
    }
  }
输出为:

1->13,2->4,3->7

我的问题是:

  • 调用
    partitionBy
    时,实际会发生什么情况?(对不起,我没有找到足够的规格)
  • 知道在我的生产环境中,不会有太多的键(对于示例为50个键)和太多的值(对于示例为100万个键),按分区进行映射真的有效吗
  • 并行化(x.toList)的成本是多少?这样做是一致的吗?(在
    mean()的输入中,我需要一个
    RDD
  • 你一个人怎么做

  • 关于

    您的代码不应该工作。无法将
    SparkContext
    对象传递给执行器。(它不是
    可序列化的
    )我也不明白你为什么需要这样做

    要计算平均值,您需要计算总和和计数,并取它们的比率。默认的分区器可以正常工作

    def meanByKey(rdd: RDD[(Int, Int)]): RDD[(Int, Double)] = {
      case class SumCount(sum: Double, count: Double)
      val sumCounts = rdd.aggregateByKey(SumCount(0.0, 0.0))(
        (sc, v) => SumCount(sc.sum + v, sc.count + 1.0),
        (sc1, sc2) => SumCount(sc1.sum + sc2.sum, sc1.count + sc2.count))
      sumCounts.map(sc => sc.sum / sc.count)
    }
    

    这是一个有效的单程计算,具有很好的通用性。

    感谢您的回答,当然它不可能工作,我没有所有的火花编码技巧反射,我已经被我的本地jvm宠坏了。然而,实际上我不需要计算平均值,而是一个复杂的ml方法,我需要一个RDD[向量]。如何从唯一的RDD[Int,Int]获取(key,RDD[Vector])列表?我没有找到解决方案。我想这是一个类似的主题:我不确定如何从
    Int
    s生成
    Vector
    s。但是,如果您希望每个键获得一个RDD,则需要拆分原始RDD,这将在链接的答案中讨论。如果它不能给你答案,我建议你再问一个问题,也许要对你想做的事情有一个清晰、高层次的解释。
    def meanByKey(rdd: RDD[(Int, Int)]): RDD[(Int, Double)] = {
      case class SumCount(sum: Double, count: Double)
      val sumCounts = rdd.aggregateByKey(SumCount(0.0, 0.0))(
        (sc, v) => SumCount(sc.sum + v, sc.count + 1.0),
        (sc1, sc2) => SumCount(sc1.sum + sc2.sum, sc1.count + sc2.count))
      sumCounts.map(sc => sc.sum / sc.count)
    }