查询Spark同时加载的hive表时如何避免错误

Posted

技术标签:

【中文标题】查询Spark同时加载的hive表时如何避免错误【英文标题】:how to avoid errors when querying hive table being loaded by Spark at the same time 【发布时间】:2020-09-17 20:25:39 【问题描述】:

我们有一个用例,我们在一些流数据之上运行用 Spark 编写的 ETL,ETL 每小时将结果写入目标 hive 表,但用户通常对目标表运行查询,我们遇到过案例由于火花同时加载表而出现查询错误。我们有哪些替代方法可以避免或尽量减少这种错误?火花作业(或蜂巢表)的任何属性?还是创建一个临时表之类的?

错误是:

java.io.FileNotFoundException: 文件不存在 [HDFS PATH]

我认为这是因为元数据显示有一个文件 A 在作业执行期间被删除。

该表按年、月、日分区(使用 HDFS 作为存储),每次 ETL 运行时都会更新(通过分区覆盖)当前日期分区。目前集群中没有启用“事务”表(即使我在没有运气的情况下在测试集群上测试了用例)

【问题讨论】:

您的数据究竟存储在哪里? S3? HDFS?还有什么是完整的堆栈跟踪?您是直接操作文件还是使用 Table 抽象? 数据存储在HDFS中,使用表抽象(将spark数据帧写入hive),更详细的错误:异常:错误:状态:失败错误:顶点失败,顶点名称=地图1,顶点ID=顶点_1585784648138_16268_15_00,诊断= [任务失败,taskId = task_1585784648138_16268_15_00_000022,诊断= [TaskAttempt 0失败,信息= [错误:运行任务时失败:java.lang.RuntimeException:java.lang.RuntimeException:java.io.IOException:java.io.FileNotFoundException :文件不存在: 【参考方案1】:

简单的选择是使用一种表格式,该表格式旨在处理并发读取和写入,如 hudi 或 delta Lake。更复杂的版本涉及使用写入者写入的分区追加表。完成后,作者更新视图以指向新数据。另一种可能的选择是在插入时对表进行分区。

【讨论】:

【参考方案2】:

有一组两个表和一个视图:

CREATE TABLE foo_a (...);
CREATE TABLE foo_b (...);
CREATE VIEW foo AS SELECT x, y, z, ... FROM foo_a;

ETL 流程的第一次迭代需要:

    同步foo_a -> foo_bfoo_b 上工作 删除视图foo 并重新创建它指向foo_b

在第 3 步之前,用户查询针对表 foo_a 运行。从切换的那一刻起,他们就与foo_b 对抗。 ETL 的下一次迭代将以相反的方式工作。

这并不完美。在 ETL 中,您需要双重存储和一些额外的复杂性。无论如何,如果出现以下情况,这种方法可能会失败:

用户很不幸,在下降和下降之间的时间很短 重新创建视图 用户提交的查询量足以在两次 ETL 迭代中运行

【讨论】:

【参考方案3】:

不确定,但检查一下

创建表 foo_a (...); 创建表 foo_b (...);

【讨论】:

以上是关于查询Spark同时加载的hive表时如何避免错误的主要内容,如果未能解决你的问题,请参考以下文章

Spark中对大表子查询加limit为什么会报Broadcast超时错误

如何在写入hive orc表时合并spark中的小文件

了解如何在 Spark 中执行 Hive SQL

查询同一张表时,spark sql 返回空值,但配置单元和 impaly 获取正常数据?

在 Pandas 数据框中加载大表时,如何避免 EC2 中的内存错误?

使用 Spark SQL 创建带有连接的 Hive 表时使用的引擎