我正在尝试解决一个简单的日志解析问题:给定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 罗布
答案 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")