保存到镶木地板子分区

时间:2015-09-29 11:01:26

标签: apache-spark apache-spark-sql

我有一个基于两个分区的目录结构,如下所示:

  People
  > surname=Doe
        > name=John
        > name=Joe
  > surname=White
        > name=Josh
        > name=Julien

我正在阅读仅包含所有Do信息的镶木地板文件,因此我直接指定surname = Doe作为我的DataFrame的输出目录。现在问题是我正在尝试在写作时添加基于名称的分区{/ 1}}。

partitionBy("name")

(outputDir包含Doe目录的路径)

这会导致如下错误:

df.write.partitionBy("name").parquet(outputDir)

任何提示如何解决?它可能是因为在surname目录中创建的 Caused by: java.lang.AssertionError: assertion failed: Conflicting partition column names detected: Partition column name list #0: surname, name Partition column name list #1: surname 文件,它给Spark提供了错误的提示 - 当我删除_SUCCESS_SUCCESS文件时,Spark能够毫无问题地读取所有内容。

2 个答案:

答案 0 :(得分:8)

我设法通过解决方法解决了这个问题 - 我不认为这是一个好主意,但我禁用了创建其他_SUCCESS和_metadata文件:

sc.hadoopConfiguration.set("mapreduce.fileoutputcommitter.marksuccessfuljobs", "false")
sc.hadoopConfiguration.set("parquet.enable.summary-metadata", "false")

这样Spark就不会对分区结构有任何愚蠢的想法。

另一个选择是保存到&#34;正确的&#34; directory - 人员和按姓氏和名称划分,但是你必须记住,唯一合理的选择是将SaveMode设置为Append并手动删除您希望被覆盖的目录(这是<强>真的容易出错):

df.write.mode(SaveMode.Append).partitionBy("surname","name").parquet("/People")

在这种情况下不要使用owerwrite SaveMode - 这将删除所有姓氏直接人员。

答案 1 :(得分:2)

sc.hadoopConfiguration.set("parquet.enable.summary-metadata", "false")

是相当明智的,如果您启用了摘要元数据,那么编写元数据文件可能会成为读写的IO瓶颈。

您的解决方案的另一种方法可能是在您的写入中添加.mode(“append”),但将原始父目录作为目标,

df.write.mode("append").partitionBy("name").parquet("/People")