Spark - 使用mapWithInputSplit时无法写入Parquet文件

时间:2016-06-17 07:06:44

标签: apache-spark apache-spark-sql

我正在尝试解决一个简单的日志解析问题:给定N个日志文件 logfile.20160601.txt logfile.29169692.txt ... 我会用日志的日期键保存镶木地板文件。

为了实现这一点,我发现了这种方式以获得inputSplit路径。

val data = sc.textFile("/logdirectory/*.*")
val logsWithFileName = data.mapPartitionsWithInputSplit { (inputSplit, iterator) =>
      val file = inputSplit.asInstanceOf[FileSplit]
      val logDateKey = getDatekeyFromPath(file)

      iterator.map { tpl => ( logDateKey, tpl._2.toString) }
      }
val logs = logsWithFileName.map(item => LogItem(item._1,item._2))
val df = logs.toDF

现在我尝试保存数据框

df.write.partitionBy(" logdatekey"," hostname")。save(" C:/temp/results.parquet")

但我收到此消息

Output directory file:/C:/temp/results.parquet already exists
org.apache.hadoop.mapred.FileAlreadyExistsException: Output directory file:/C:/temp/results.parquet already exists
    at org.apache.hadoop.mapred.FileOutputFormat.checkOutputSpecs(FileOutputFormat.java:132)
    at org.apache.spark.rdd.PairRDDFunctions$$anonfun$saveAsHadoopDataset$1.apply$mcV$sp(PairRDDFunctions.scala:1179)

有没有人尝试过这种奇怪的行为?这可能与输入拆分的使用有关吗?

非常感谢adavance 罗布

1 个答案:

答案 0 :(得分:1)

你的错误信息是allo。您正在尝试编写已存在的输出。

您只需要可用的保存操作:

  

保存操作可以选择使用SaveMode,它指定如何处理现有数据(如果存在)。重要的是要意识到这些保存模式不使用任何锁定并且不是原子的。此外,执行覆盖时,将在写出新数据之前删除数据。

  • SaveMode.ErrorIfExists(默认情况下的行为)将DataFrame保存到数据源时,如果数据已经存在,则会引发异常。

  • SaveMode.Append - 将DataFrame保存到数据源时,如果数据/表已存在,则DataFrame的内容应附加到现有数据中。

  • SaveMode.Overwrite - 表示在将DataFrame保存到数据源时,如果数据/表已经存在,则预计现有数据将被DataFrame的内容覆盖。

  • SaveMode.Ignore - 表示在将DataFrame保存到数据源时,如果数据已存在,则保存操作不会保存DataFrame的内容,也不会更改现有数据。这类似于SQL中的CREATE TABLE IF NOT EXISTS。

因此,如果您想要覆盖现有数据,则应执行以下操作:

import org.apache.spark.sql.SaveMode

df.write.partitionBy("logdatekey", "hostname").mode(SaveMode.Overwrite).save("C:/temp/results.parquet")