我有一个相当庞大的Parquet文件,需要更改其中一列的值。一种方法是在源文本文件中更新这些值并重新创建Parquet文件,但我想知道是否有更便宜、更容易的解决方案。
我有一个相当庞大的Parquet文件,需要更改其中一列的值。一种方法是在源文本文件中更新这些值并重新创建Parquet文件,但我想知道是否有更便宜、更容易的解决方案。
让我们从基础知识开始:
Parquet是一种需要保存在文件系统中的文件格式。
关键问题:
答案:
parquet.hadoop.ParquetFileWriter
仅支持CREATE
和OVERWRITE
;没有append
模式。(不确定但其他实现可能会改变 - parquet设计支持append
)
HDFS允许使用dfs.support.append
属性对文件进行追加操作。
Spark框架不支持向现有parquet文件追加,并且没有计划;请参见此JIRA:https://issues.apache.org/jira/browse/SPARK-18199
在分布式系统中追加到现有文件不是一个好主意,特别是考虑到我们可能同时拥有两个写入者。
更多详细信息在此处:
有一些解决方法,但需要按照特定方式创建parquet文件以便更容易更新。
最好的做法:
A. 使用行组来创建parquet文件。您需要优化行组中可以放入多少行数据,以使数据压缩和字典编码等功能停止运行。
B. 逐个扫描行组并找出需要更新的行组。为每个修改后的行组生成包含修改数据的新parquet文件。逐个处理一个行组的数据比处理整个文件更节省内存。
C. 通过追加未修改的行组和使用读入一个parquet文件生成的修改后的行组来重建原始parquet文件。
使用行组重新组装parquet文件非常快速。
理论上,如果只去掉页脚(统计信息),添加新的行组并添加更新统计信息的新页脚,就可以轻松地将内容添加到现有的parquet文件中,但没有支持此操作的API /库。
您需要重新创建文件,这是Hadoop的方法。特别是当文件被压缩时。
另一种方法(在大数据中非常常见)是在另一个Parquet(或ORC)文件上执行更新,然后在查询时进行JOIN / UNION操作。
嗯,在2022年,我强烈建议使用湖屋解决方案,例如deltaLake或Apache Iceberg。它们会为您处理这个问题。