如何在执行者身上使用SparkContext
(创建SparkSession
或Cassandra会话)?
如果我将其作为参数传递给foreach
或foreachPartition
,那么它将具有null
值。我应该在每个执行者中创建一个新的SparkContext
吗?
我要做的是如下:
读取包含数百万个XML文件的转储目录:
dumpFiles = Directory.listFiles(dumpDirectory)
dumpFilesRDD = sparkContext.parallize(dumpFiles, numOfSlices)
dumpFilesRDD.foreachPartition(dumpFilePath->parse(dumpFilePath))
在parse()
中,每个XML文件都使用Spark SQL进行验证,解析并插入到多个表中。只有有效的XML文件才会显示可以保存的相同类型的对象。在插入其中一个表之前,数据的一部分需要被其他键替换。
为了做到这一点,函数SparkContext
中需要parse
才能使用sparkContext.sql()
。
答案 0 :(得分:2)
如果我改写你的问题,你想要的是:
这是一个典型的提取,转换和加载(ETL)过程,它在Spark SQL中非常容易。
可以使用单独的包spark-xml来加载XML文件:
spark-xml 用于使用Apache Spark解析和查询XML数据的库,用于Spark SQL和DataFrame。结构和测试工具大多是从Spark Data的CSV数据源复制的。
你可以安装"使用--packages
命令行选项的包:
$SPARK_HOME/bin/spark-shell --packages com.databricks:spark-xml_2.11:0.4.1
引用spark-xml Scala API(使用SparkSession
进行一些更改):
// Step 1. Loading XML files
val path = "the/path/to/millions/files/*.xml"
val spark: SparkSession = ???
val files = spark.read
.format("com.databricks.spark.xml")
.option("rowTag", "book")
.load(path)
这使得第一个要求几乎毫无疑问。您已经通过Spark SQL了解了百万个XML文件。
第2步是解析行(来自XML文件)并标记要保存到适当表的行。
// Step 2. Transform them (using parse)
def parse(line: String) = ???
val parseDF = files.map { line => parse(line) }
您的parse
函数可能会返回某些内容(作为主要结果)以及某些内容应保存到的表格。
使用表格标记,您可以将parseDF
拆分为每个表的DataFrame。
val table1DF = parseDF.filter($"table" === "table1")
等等(每张表)。
// Step 3. Insert into DB
table1DF.write.option(...).jdbc(...)
这只是你可能真正之后的概述,但这是一般的模式。将您的管道分解为可消化的块,并一次处理一个块。
答案 1 :(得分:1)
重要的是要记住,在Spark中,我们不应该根据执行者进行编程。
在Spark编程模型中,您的驱动程序主要是一个自包含的程序,其中某些部分将自动转换为物理执行计划。最终,一系列任务分布在工人/执行者之间。
当您需要为每个分区执行某些操作时,可以使用mapPartitions()之类的东西。有关详细信息,请参阅Spark : DB connection per Spark RDD partition and do mapPartition。请注意dbConnection对象如何包含在函数体中。
您不清楚参数的含义。如果只是数据(不是数据库连接或类似数据),我认为您需要使用boradcast variable。