Apache Spark groupByKey - > saveAsTextfile

时间:2014-09-05 19:50:09

标签: scala apache-spark

我有一个包含许多未排序行的巨大XML文件:

<row>
  <field name="f1">group</field>
  <field name="f2">number</field>
  <field name="f3">number2</field>
</row>

我希望使用spark将具有不同数字的每个组(f1)提取到一个单独的文件中。

现在我试图先使用map,distinct和collect,然后遍历这个组数组来提取所有组(~50)。使用原始RDD,我过滤与当前组匹配的所有行saveToTextFile。   - 工作,但我很确定这种方式效率最低。

因此我改变了我的xml导入器以返回(f1,(f2,f3))并尝试:

rdd.groupByKey(numPartitions).mapPartitions(part => {
  part.map(data => {
    val group = data._1
    val numbers = data._2
    ...
}

这是我得到多远,因为现在数字是Iterable [(String,String)],而不是RDD。

我的想法是基本的(伪代码):

 rdd.groupByKey(numPartitions).map((group, numbers) => { 
    numbers.distinct.map(OutputFormatter(_)).
      saveAsTextFile(s"$target$group") 
 }

这里的numPartitions应该与worker的大小相匹配,每个worker有一个组(我也喜欢在这里测试行为,但这是OT)

数字不能在这里成为RDD是正确的,因为groupByKey需要先收集数据吗? 如果不是,我错过了什么?

此操作有一个共同的最佳做法吗?我是spark / hadoop / etc的新手

谢谢。

1 个答案:

答案 0 :(得分:0)

我可以想到以下方法,我认为它与您使用过滤的原始解决方案的精神相似,除非我们没有明确地收集到数组。这接近你需要的吗?

def extractGroup(row: Row) = ???

def extractNumbers(row: Row) = ???

val keyed = rdd.keyBy(extractGroup _) 

keyed
  .map { case (group, row) => group }
  .distinct
  .foreach { group =>
     keyed
       .filter { _._1 == group } 
       .map { case (_, row) => extractNumbers(row) }
       .distinct
       .map(OutputFormatter(_))
       .saveAsTextFile(???)
   }