我在s3中有实木复合地板文件,具有以下分区: 年/月/日/ some_id 我想使用Spark(PySpark)在过去的 14天中每天进行一次UPSERT-我想替换s3中的现有数据(每个分区一个镶木文件),但不想删除14天之前的日子.. 我尝试了两种保存模式: 追加-不好,因为它只是添加了另一个文件。 覆盖-正在删除过去的数据和其他分区的数据。
有什么方法或最佳实践可以克服吗?我应该在每次运行中从s3中读取所有数据,然后再次写回吗?也许重命名文件以便 append 替换s3中的当前文件?
非常感谢!
答案 0 :(得分:4)
我通常会做类似的事情。以我为例,我进行了ETL并将一天的数据附加到 parquet 文件中:
关键是要处理要写入的数据(在我的情况下为实际日期),请确保按date
列进行分区,并覆盖当前日期的所有数据>。
这将保留所有旧数据。例如:
(
sdf
.write
.format("parquet")
.mode("overwrite")
.partitionBy("date")
.option("replaceWhere", "2020-01-27")
.save(uri)
)
您还可以查看delta.io,它是镶木地板格式的扩展,提供了一些有趣的功能,例如 ACID 交易。
答案 1 :(得分:1)
据我所知,S3没有更新操作。一旦将对象添加到s3,就无法修改。 (您必须替换另一个对象或附加文件)
无论如何,您都必须读取所有数据,您可以指定要读取的时间轴,分区修剪有助于仅读取时间轴内的分区。
答案 2 :(得分:1)
感谢所有有用的解决方案。 我最终使用了适合我的用例的一些配置-在编写镶木地板时使用 overwrite 模式以及以下配置:
我添加了此配置:
spark.conf.set("spark.sql.sources.partitionOverwriteMode", "dynamic")
使用此配置的spark将仅覆盖要写入其数据的分区。所有其他(过去)分区均保持不变-参见此处:
https://jaceklaskowski.gitbooks.io/mastering-spark-sql/spark-sql-dynamic-partition-inserts.html