Spark累加器:正确的累加器有时很多或总是一个?

时间:2016-02-13 04:43:33

标签: scala apache-spark spark-dataframe

我正在尝试使用Spark累加器来删除性能较差的查询组。

import org.apache.spark._
object CountPairsParam extends AccumulatorParam[Map[Int, Set[Int]]] {

  def zero(initialValue: Map[Int, Set[Int]]): Map[Int, Set[Int]] = {
    Map.empty[Int, Set[Int]]
  }

  def addInPlace(m1: Map[Int, Set[Int]], m2: Map[Int, Set[Int]]): Map[Int, Set[Int]] = {
    val keys = m1.keys ++ m2.keys
     keys.map((k: Int) => (k -> (m1.getOrElse(k, Set.empty[Int]) ++ m2.getOrElse(k, Set.empty[Int])))).toMap
  }
}
val accum = sc.accumulator(Map.empty[Int, Set[Int]])(CountPairsParam)
srch_destination_id_distinct.foreach(r => try{accum += Map(r(0).toString.toInt -> Set(r(1).toString.toInt))} catch {case ioe: NumberFormatException =>  Map.empty[Int, Set[Int]]})

在我的累加器中,我假设m2不会总是在我的foreach循环中创建的单个项目集,并且有时Spark将使用此方法添加两个具有多个键的不同地图。但正因如此,我的表现很低。正确的Map是否总是通过一个项目进入累加器,从每个循环的my设置,或者我是否需要将此性能权交换掉?

1 个答案:

答案 0 :(得分:3)

一般情况下,您应该避免使用Accumulators进行调试,因为据我所知,RDD的每个条目只会被添加到" #34;完全进入Accumulator一次。

也许尝试这样的事情:

import scala.collection.mutable.HashSet
import scala.util.Try

val result = srch_destination_id_distinct.flatMap(r => 
  Try((r(0).toString.toInt, r(1).toString.toInt)).toOption
).aggregateByKey(HashSet.empty[Int])(
  (set, n) => set += n,
  (set1, set2) => set1 union set2
).mapValues(_.toSet).collectAsMap

seqOp方法的combOpaggregate参数之间的区别也允许我们避免&#34;包装&#34; <{1}}中RDD的每个元素与您的方法一样。