我有一个基于两个分区的目录结构,如下所示:
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能够毫无问题地读取所有内容。
答案 0 :(得分:8)
我设法通过解决方法解决了这个问题 - 我不认为这是一个好主意,但我禁用了创建其他_SUCCESS和_metadata文件:
sc.hadoopConfiguration.set("mapreduce.fileoutputcommitter.marksuccessfuljobs", "false")
sc.hadoopConfiguration.set("parquet.enable.summary-metadata", "false")
这样Spark就不会对分区结构有任何愚蠢的想法。
另一个选择是保存到"正确的" 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")