什么是在scala中合并rdds的最佳实践

时间:2016-04-14 04:41:31

标签: scala apache-spark

我有多个RDD作为结果并希望合并它们,它们具有相同的格式:

RDD(id, HashMap[String, HashMap[String, Int]])
    ^             ^        ^
    |             |        |
  identity     category   distribution of the category

以下是rdd:

的示例
(1001, {age={10=3,15=5,16=8, ...}})

String的第一个键HashMap[String, HashMap]是统计信息的类别,HashMap[String, Int]中的HashMap[String, HashMap]是该类别的分布。在计算了不同类别的每个分布之后,我想通过标识合并它们,以便我可以将结果存储到数据库中。这是我目前得到的:

def mergeRDD(rdd1: RDD[(String, util.HashMap[String, Object])],
              rdd2:RDD[(String, util.HashMap[String, Object])]): RDD[(String, util.HashMap[String, Object])] = {

  val mergedRDD = rdd1.join(rdd2).map{
    case (id, (m1, m2)) => {
      m1.putAll(m2)
      (id, m1)
    }
  }
  mergedRDD
}
val mergedRDD = mergeRDD(provinceRDD, mergeRDD(mergeRDD(levelRDD, genderRDD), actionTypeRDD))

我写了一个函数mergeRDD,这样我每次都可以合并两个rdds,但是我发现函数不是很优雅,作为scala的新手,任何鼓舞人心的人都会受到赞赏。

2 个答案:

答案 0 :(得分:2)

我没有看到任何简单的方法来实现这一点,而没有达到性能。 原因是,您不是简单地合并两个rdd,而是希望您的hashmap在rdd联合后具有合并值。

现在,你的合并功能是错误的。在当前状态中,join实际上会执行内部联接,错过rdd中不存在于其他行中的行。

正确的方式就像是。

val mergedRDD = rdd1.union(rdd2).reduceByKey{
    case (m1, m2) => {
      m1.putAll(m2)
      }
}

答案 1 :(得分:0)

您可以将java.util.HashMap替换为scala.collection.immutable.Map

从那里:

val rdds      = List(provinceRDD, levelRDD, genderRDD, actionTypeRDD)
val unionRDD  = rdds.reduce(_ ++ _)
val mergedRDD = unionRDD.reduceByKey(_ ++ _)

这是假设类别在rdds之间不重叠。