更新 apache parquet 文件中的值

Posted

技术标签:

【中文标题】更新 apache parquet 文件中的值【英文标题】:Updating values in apache parquet file 【发布时间】:2015-05-04 10:30:33 【问题描述】:

我有一个非常大的镶木地板文件,我需要在其中更改其中一列的值。一种方法是更新源文本文件中的这些值并重新创建镶木地板文件,但我想知道是否有更便宜且整体更简单的解决方案。

【问题讨论】:

没有。您必须重新创建文件。 @DanOsipov 谢谢。我认为这种限制是由于使用了各种压缩算法,这些算法不容易甚至不可能更新列值。 我想说,这是一个更基本的问题,而不是镶木地板的具体问题。在大数据量的世界中,拼花地板被大量使用,不变性是您想要关心的事情。从这个角度来看,您希望加载数据、对其进行转换,然后再次写入。您可能会考虑只编写您需要的列,因为它是按列格式,所以效率更高。 我了解到您想要更新之前运行中已写入的字段。也许这篇文章可以提供帮助。我不是在推销任何产品。请关注所涉及的概念,而不是宣传的产品。 databricks.com/blog/2018/10/29/… 【参考方案1】:

让我们从基础开始:

Parquet 是一种文件格式,需要保存在文件系统中。

关键问题:

    parquet 是否支持append 操作? 文件系统(即HDFS)是否允许append 处理文件? 作业框架 (Spark) 能否实现append 操作?

答案:

    parquet.hadoop.ParquetFileWriter只支持CREATEOVERWRITE;没有append 模式。 (不确定,但这可能会在其他实现中发生变化——镶木地板设计确实支持append

    HDFS 允许 append 使用 dfs.support.append 属性处理文件

    Spark 框架不支持 append 到现有的 parquet 文件,并且没有计划; see this JIRA

在分布式系统中附加到现有文件不是一个好主意,尤其是考虑到我们可能同时有两个写入器。

更多细节在这里:

http://bytepadding.com/big-data/spark/read-write-parquet-files-using-spark/

http://bytepadding.com/linux/understanding-basics-of-filesystem/

【讨论】:

感谢您的详细回答和背景信息。这很有帮助【参考方案2】:

有一些变通方法,但您需要以某种方式创建 parquet 文件以使其更易于更新。

最佳实践:

A.使用行组创建镶木地板文件。在数据压缩和字典编码等功能停止发挥作用之前,您需要优化可以进入行组的数据行数。

B.一次扫描一个行组并找出需要更新哪些行组。为每个修改的行组生成带有修改数据的新 parquet 文件。一次处理一个行组的数据而不是文件中的所有数据,内存效率更高。

C.通过附加未修改的行组和通过读取每个行组的一个 parquet 文件生成的修改后的行组来重建原始 parquet 文件。

使用行组重新组装 parquet 文件速度惊人。

理论上,如果您只是剥离页脚(统计信息),附加新行组并添加带有更新统计信息的新页脚,那么附加到现有 parquet 文件应该很容易,但是没有支持它的 API/库..

【讨论】:

【参考方案3】:

看看这个不错的博客,它可以回答你的问题并提供一种使用 Spark(Scala) 执行更新的方法:

http://aseigneurin.github.io/2017/03/14/incrementally-loaded-parquet-files.html

从博客复制和粘贴:

当我们需要在我们的数据结构 (Parquet) 中编辑不可变的数据时。

您可以将分区添加到 Parquet 文件,但不能就地编辑数据。

但最终我们可以改变数据,我们只需要接受我们不会在原地这样做。我们需要结合使用模式和 UDF 重新创建 Parquet 文件,以纠正错误数据。

如果你想在 Parquet 中增量追加数据(你没问这个问题,对其他读者还是有用的) 参考这篇写得很好的博客:

http://aseigneurin.github.io/2017/03/14/incrementally-loaded-parquet-files.html

免责声明:我没有写过那些博客,我只是读了它,发现它可能对其他人有用。

【讨论】:

我知道这个问题比简单地附加分区更复杂一些,正如博客文章所解释的那样。假设一些数据在更多数据到达之前是有效的,这可以在 SQL 数据库上轻松实现,但需要创造性,以防您不能只更新记录的字段,这就是 parquet 文件的情况。【参考方案4】:

您必须重新创建文件,这是 Hadoop 方式。特别是如果文件被压缩。

另一种方法(在大数据中非常常见)是在另一个 Parquet(或 ORC)文件上进行更新,然后在查询时进行 JOIN / UNION。

【讨论】:

以上是关于更新 apache parquet 文件中的值的主要内容,如果未能解决你的问题,请参考以下文章

雪花:因异常 java.io.IOException 失败:org.apache.parquet.io.ParquetDecodingException:无法在块 -1 中读取 0 处的值

如何在 R 中读取 Parquet 并将其转换为 R DataFrame?

java - 如何在类似于pyspark的java分区中写入parquet文件?

iceberg org.apache.iceberg.parquet.Parquet parquet file read

iceberg org.apache.iceberg.parquet.Parquet parquet file read

iceberg org.apache.iceberg.parquet.Parquet parquet file read