Scala在Spark中收集效率低下?

时间:2016-03-22 14:33:03

标签: scala apache-spark

我现在开始学习使用Scala的spark。我正在处理的问题需要我读取一个文件,拆分某个字符的每一行,然后过滤其中一列与谓词匹配的行,最后删除一列。因此,基本的,天真的实现是一个地图,然后是一个过滤器,然后是另一个地图。

这意味着要经历3次收藏,这对我来说似乎是不合理的。所以我尝试用一​​个集合替换它们(将部分函数作为参数的集合)。令我惊讶的是,这让它运行得慢得多。我在常规的Scala集合上尝试了本地化;正如预期的那样,后一种做法要快得多。

那为什么呢?我的想法是地图和过滤器和地图不是按顺序应用,而是混合成一个操作;换句话说,当一个动作强制评估时,将检查列表的每个元素,并执行待处理的操作。是对的吗 ?但即便如此,为什么收集表现如此糟糕呢?

编辑:显示我想要做的代码示例:

天真的方式:

sc.textFile(...).map(l => {
  val s = l.split(" ") 
  (s(0), s(1))
}).filter(_._2.contains("hello")).map(_._1)

收集方式:

sc.textFile(...).collect {
  case s if(s.split(" ")(0).contains("hello")) => s(0)
}

1 个答案:

答案 0 :(得分:4)

答案在于collect

的实施
/**
 * Return an RDD that contains all matching values by applying `f`.
 */
def collect[U: ClassTag](f: PartialFunction[T, U]): RDD[U] = withScope {
  val cleanF = sc.clean(f)
  filter(cleanF.isDefinedAt).map(cleanF)
}

正如您所看到的,它与filter - > map的序列相同,但效率较低。

在scala中,isDefinedAt和[{1}}评估apply部分的PartialFunctionif方法。

所以,在你的"收集"示例split将针对每个输入元素执行两次。