首页 > 解决方案 > 为 impala 表无缝覆盖底层 parquet 数据

问题描述

我有一个由另一个团队使用的镶木地板文件支持的 Impala 表。每天我都会运行一个批处理 Spark 作业,它会覆盖现有的 parquet 文件(创建新数据集,现有文件将被删除并创建新文件)

我们的 Spark 代码如下所示

dataset.write.format("parquet").mode("overwrite").save(path)

在此更新期间(覆盖 parquet 数据文件,然后覆盖REFRESHImpala 表),如果有人访问该表,那么他们最终会出现错误,指出基础数据文件不存在。

是否有任何解决方案或解决方法可用于此问题?因为我不希望其他团队在访问表时在任何时间点看到错误。

也许我可以将新的数据文件写入不同的位置,然后让 Impala 表指向那个位置?

标签: apache-sparkparquetimpala

解决方案


您看到的行为是因为 Impala 的设计方式。Impala 从 HMS 获取表的元数据,例如表结构、分区详细信息、HDFS 文件路径以及来自 NameNode 的相应 HDFS 文件路径的块详细信息。所有这些详细信息都由 Catalog 获取,并将分布在 Impala 守护程序中以供执行。

当表的底层文件被删除并在 Impala 外部写入新文件时,需要执行 REFRESH 以便获取新文件详细信息(例如文件和相应的块详细信息)并跨守护进程分发。这样,Impala 就会知道新写入的文件。

由于您正在覆盖文件,Impala 查询将无法找到它知道的文件,因为它们已经被删除并且正在写入新文件。这是一个预期的事件。

作为解决方案,您可以执行以下操作之一,

  1. 将新文件追加到表的同一 HDFS 路径中,而不是覆盖。这样,在表上运行的 Impala 查询仍然会返回结果。然而,结果将只是较旧的数据(因为 Impala 还不知道新文件),但在发生覆盖期间将避免您所说的错误。在表的目录中创建新文件后,您可以执行 HDFS 操作以删除这些文件,然后为该表执行 Impala REFRESH 语句。

或者

  1. 正如您所说,您可以在不同的 HDFS 路径中写入新的 parquet 文件,一旦写入完成,您可以 [删除旧文件,将新文件移动到表的实际 HDFS 路径中,然后是 REFRESH ][对表发出 ALTER 语句以修改指向新目录的表数据的位置]。如果这是一个日常过程,您可能必须通过一个脚本来实现这一点,该脚本在 Spark 完成的成功写入过程中运行,通过将目录(新目录和旧目录)作为参数传递。

希望这可以帮助!


推荐阅读