Spark Scala大XML文件按行属性拆分

时间:2019-01-04 13:45:23

标签: xml scala performance apache-spark

我试图在Scala-Spark中将一个较大的xml文件(1 TeraByte)拆分为较小的文件。这是一个示例XML,如下所示(test1.xml)。 “ LOG”是根标签,“ LgRec”是行标签,并且要求根据“ RecId”(LgRec的属性)值将其拆分为较小的文件。因此,在这种情况下,它将产生3个文件test1_AA.xml,test1_BB.xml,test1_CC.xml。

我使用DATABRICKS XML库编写了代码,并在一个较小的文件上进行了测试。当我为1 TB文件运行此程序时,我的问题是有更好的方法来执行此操作。 Spark是否将整个1 TB DF和较小的DF保留在内存中,这意味着我的Spark集群需要大约2TB +的内存?

欣赏您的想法

test1.xml (input file)
<?xml version="1.0" encoding="UTF-8"?>
<LOG>
  <LgRec RecId="AA">
    <UpdRec>
      <field num="001">aaaa</field>
      <field num="002">100</field>
      <field num="003">100.10</field>
      <field num="004">20181125</field>
      <field num="005">101010.123</field>
    </UpdRec>
  </LgRec>
  <LgRec RecId="BB">
    <UpdRec>
      <field num="001">xaaa</field>
      <field num="002">1100</field>
      <field num="003">1100.10</field>
      <field num="004">20181125</field>
      <field num="005">111111.123</field>
    </UpdRec>
  </LgRec>
  <LgRec RecId="CC">
    <UpdRec>
      <field num="001">zaaaa</field>
      <field num="002">3100</field>
      <field num="003">3100.10</field>
      <field num="004">20181225</field>
      <field num="005">131313.123</field>
    </UpdRec>
  </LgRec>
</LOG>

test1_AA.xml  (output file)
<LOG>
  <LgRec RecId="AA">
    <UpdRec>
      <field num="001">aaaa</field>
      <field num="002">100</field>
      <field num="003">100.10</field>
      <field num="004">20181125</field>
      <field num="005">101010.123</field>
    </UpdRec>
  </LgRec>

test1_BB.xml  (output file)
  <LgRec RecId="BB">
    <UpdRec>
      <field num="001">xaaa</field>
      <field num="002">1100</field>
      <field num="003">1100.10</field>
      <field num="004">20181125</field>
      <field num="005">111111.123</field>
    </UpdRec>
  </LgRec>

test1_CC.xml  (output file)
  <LgRec RecId="CC">
    <UpdRec>
      <field num="001">zaaaa</field>
      <field num="002">3100</field>
      <field num="003">3100.10</field>
      <field num="004">20181225</field>
      <field num="005">131313.123</field>
    </UpdRec>
  </LgRec>
</LOG>

这是代码

import org.apache.spark.sql._
import org.apache.spark.sql.types._
import com.databricks.spark.xml._


object splitXML {

  def main(args: Array[String]) = {

    val spark = SparkSession
      .builder()
      .appName("splitXML")
      .master("local")
      .getOrCreate()

    import spark.implicits._

    val inputFile = "test1.xml"

    val outputFilePrefix = "test1_"
    val outputFileSuffix = ".xml"

    val inputXMLDF = spark.read
                     .option("roottag", "LOG")
                     .option("rowTag" , "LgRec")
                     .xml(inputFile)

    //get distinct recId's
    val recTypeDF = inputXMLDF.select("_RecId").distinct() 

    //for each recid filter the DF by recId and output the file
    recTypeDF.collect().map(row => {
                                     println("row = " + row(0) )
                                     inputXMLDF.filter(inputXMLDF("_RecId")===row(0))
                                               .write
                                               .option("roottag", "LOG")
                                               .option("rowTag" , "LgRec")
                                               .xml(outputFilePrefix + row(0) + outputFileSuffix)

                                   })

    spark.close()
  }

}

0 个答案:

没有答案