我有一个 Impala 表背后的Parquet文件是由另一个团队使用。每天我运行一个批量spark作业,覆盖现有的Parquet地板文件(创建新的数据集,现有的文件将被删除,新的文件将被创建)
我们的Spark代码是这样的 dataset.write.format("parquet").mode("overwrite").save(path)
在此更新期间(覆盖Parquet数据文件,然后 REFRESH
impala表),如果有人访问该表,那么他们最终会错误地说底层数据文件不在那里。
是否有任何解决方案或解决方法可用于此问题?因为我不希望其他团队在访问表时看到任何时间点的错误。
也许我可以把新的数据文件写到不同的位置,然后让impala表指向那个位置?
1条答案
按热度按时间nxagd54h1#
你所看到的行为是因为 Impala 的工作方式。impala从hms获取表的元数据,如表结构、分区详细信息、hdfs文件路径,并从namenode获取相应hdfs文件路径的块详细信息。所有这些细节都由catalog获取,并将分发到impala守护进程中执行。
当删除表的底层文件并在impala外部写入新文件时,需要执行刷新,以便获取新文件的详细信息(如文件和相应的块详细信息)并在守护进程中分发。这样, Impala 就会意识到新编写的文件。
由于您正在覆盖这些文件,impala查询将无法找到它所知道的文件,因为它们已经被删除,并且正在写入新文件。这是一个预期的事件。
作为解决方案,您可以执行以下操作之一,
将新文件附加到表的同一hdfs路径中,而不是覆盖。这样,在表上运行的impala查询仍然会返回结果。但是,结果只会是较旧的数据(因为impala还不知道新的文件),但是您所说的错误将在覆盖发生时被避免。一旦在表的目录中创建了新文件,您就可以执行hdfs操作来删除这些文件,然后为该表执行impala refresh语句。
或
正如您所说的,您可以在不同的hdfs路径中写入新的Parquet文件,一旦写入完成,您可以[删除旧文件,将新文件移到表的实际hdfs路径中,然后刷新]或[对表发出alter语句,修改指向新目录的表数据的位置]。如果它是一个日常进程,那么您可能需要通过一个脚本来实现这一点,该脚本在spark成功地编写了一个进程之后运行,并将目录(新目录和旧目录)作为参数传递给spark。
希望这有帮助!