我想一个DataFrame
保存到HDFS使用DataFrameWriter
木地板格式,三个值分割,就像这样:如何在Spark中分区和写入DataFrame而不删除没有新数据的分区?
dataFrame.write.mode(SaveMode.Overwrite).partitionBy("eventdate", "hour", "processtime").parquet(path)
正如this question提到的,partitionBy
将在path
删除分区的全部现有层次结构和用dataFrame
中的分区替换它们。由于特定日期的新增量数据将周期性地发布,我想要的是只替换dataFrame
有数据的层次结构中的那些分区,而其他分区不变。
要做到这一点看来我需要保存每个分区单独使用它的完整路径,像这样:
singlePartition.write.mode(SaveMode.Overwrite).parquet(path + "/eventdate=2017-01-01/hour=0/processtime=1234567890")
但是我无法理解来组织数据为单分区的最好办法DataFrame
s,这样我就可以用他们的完整路径写出来。一个想法是这样的:
dataFrame.repartition("eventdate", "hour", "processtime").foreachPartition ...
但foreachPartition
上Iterator[Row]
这是不理想的写出来,以平面形式运行。
我还考虑使用select...distinct eventdate, hour, processtime
来获取分区列表,然后通过每个分区过滤原始数据帧并将结果保存到其完整分区路径。但是,对于每个分区而言,独特的查询加上一个过滤器似乎并不是非常有效,因为它会进行大量的过滤/写入操作。
我希望有一个更清洁的方法来保存dataFrame
没有数据的现有分区?
感谢您的阅读。
Spark版本:2.1
你测试,如果当你写的一样数据两次取代旧分区?从我的测试中,它实际上在分区目录内创建了一个新的parquet文件,导致数据翻倍。我在Spark 2.2上。 – suriyanto