Spark多输出路径导致多输入读取

时间:2017-10-19 00:13:01

标签: scala apache-spark

首先,为标题道歉,我不确定如何雄辩地描述这一点。

我有一个spark作业,它将日志解析为JSON,然后使用spark-sql将特定列转换为ORC并写入各种路径。例如:

val logs = sc.textFile("s3://raw/logs")
val jsonRows = logs.mapPartitions(partition => {
  partition.map(log => {
    logToJson.parse(log)
  }
}

jsonRows.foreach(r => {
  val contentPath = "s3://content/events/"
  val userPath = "s3://users/events/"
  val contentDf = sqlSession.read.schema(contentSchema).json(r)
  val userDf = sqlSession.read.schema(userSchema).json(r)
  val userDfFiltered = userDf.select("*").where(userDf("type").isin("users")
  // Save Data
  val contentWriter = contentDf.write.mode("append").format("orc")
  eventWriter.save(contentPath)
  val userWriter = userDf.write.mode("append").format("orc")
  userWriter.save(userPath)

当我写这篇文章时,我希望解析会发生一次,然后它会写入相应的位置。但是,似乎它正在执行文件中的所有代码两次 - 一次用于content,一次用于users。这是预期的吗?我希望我不会最终从S3传输数据并解析两次,因为这是最大的瓶颈。我附加了一个来自Spark UI的图像,以显示单个流窗口的任务重复。感谢您的任何帮助,您可以提供! Spark Application UI

1 个答案:

答案 0 :(得分:0)

好的,这种嵌套的DF是不行的。 Seq旨在成为 big 数据集的数据结构,这些数据集不符合常规数据结构(例如ListDataFrame)并且需要以分布式方式处理。 不是只是另一种数组。你在这里尝试做的是创建一个DataFrames每个日志行,这没什么意义。

根据您在此处发布的(不完整)代码,我想从您的原始输入(日志)中创建两个新的val logs = sc.textFile("s3://raw/logs") val contentPath = "s3://content/events/" val userPath = "s3://users/events/" val jsonRows = logs .mapPartitions(partition => { partition.map(log => logToJson.parse(log)) } .toDF() .cache() // Or use persist() if dataset is larger than will fit in memory jsonRows .write .format("orc") .save(contentPath) jsonRows .filter(col("type").isin("users")) .write .format("orc") .save(userPath) ,然后您希望将其存储在两个不同的位置。像这样:

var pippo = "pippo";

var arr = ['BUTTON','BADGE','CHECKBOX'];

if(arr.indexOf(pippo) > -1){ 
  console.log("contained!");
}
else{
  console.log("not contained!");
}

希望这有帮助。