将 Avro 文件加载到 BigQuery 失败并出现内部错误

Posted

技术标签:

【中文标题】将 Avro 文件加载到 BigQuery 失败并出现内部错误【英文标题】:Loading Avro-file to BigQuery fails with an internal error 【发布时间】:2016-04-20 08:38:08 【问题描述】:

Google BigQuery 在March 23, 2016 announced“添加了对加载操作的 Avro 源格式的支持,并作为 BigQuery API 或命令行工具中的联合数据源”。它说here“这是 Avro 格式支持的 Beta 版本。此功能不包含在任何 SLA 或弃用政策中,并且可能会受到向后不兼容的更改。”。但是,我希望该功能能够正常工作。

我没有找到任何关于如何使用 Avro 格式进行加载的代码示例。我也没有找到关于如何使用bq-tool 进行加载的示例。

这是我的实际问题。我无法将 Avro 格式的数据加载到 BigQuery。

使用bq-tool 会发生以下情况。数据集、表名和桶名已被混淆:

$ bq extract --destination_format=AVRO dataset.events_avro_test gs://BUCKET/events_bq_tool.avro Waiting on bqjob_r62088699049ce969_0000015432b7627a_1 ... (36s) Current status: DONE $ bq load --source_format=AVRO dataset.events_avro_test gs://BUCKET/events_bq_tool.avro Waiting on bqjob_r6cefe75ece6073a1_0000015432b83516_1 ... (2s) Current status: DONE BigQuery error in load operation: Error processing job 'dataset:bqjob_r6cefe75ece6073a1_0000015432b83516_1': An internal error occurred and the request could not be completed.

基本上,我是从一个表中提取并插入到同一个表中,从而导致内部错误。

此外,我有一个 Java 程序,它执行相同的操作(从表 X 中提取并加载到表 X),结果相同(内部错误)。但我认为上面尽可能清楚地说明了这个问题,因此我没有在这里分享代码。在 Java 中,如果我从一个空表中提取并插入它,插入作业不会失败。

我的问题是

我认为 BigQuery API 永远不会因内部错误而失败。为什么我的测试会发生这种情况? 提取的 Avro 文件是否与插入作业兼容? 似乎没有规范插入作业中的 Avro 架构是什么样的,至少我找不到。可以创建文档吗?

2016 年 4 月 25 日更新:

到目前为止,我已经设法让 Avro 加载作业不给出基于不使用 REQUIRED 字段的提示的内部错误。但是,我还没有设法加载非空值。

考虑这个 Avro 模式:

"type": "record", "name": "root", "fields": [ "name": "x", "type": "string" ]

BigQuery 表有一列,x,即NULLABLE

如果我插入 N 行(我已经尝试过一两行)(x 是例如 1),我在 BigQuery 中得到 N 行,但 x 始终具有值 null

如果我将表格更改为 XREQUIRED,则会出现内部错误。

【问题讨论】:

【参考方案1】:

BQ 架构与 Avro 架构之间没有完全匹配,反之亦然,因此当您将 BQ 表导出到 Avro 文件然后再导入时,架构会有所不同。我看到您的负载的目标表已经存在,在这种情况下,当目标表的架构与我们从 Avro 架构转换的架构不匹配时,我们会抛出错误。不过这应该是外部错误,我们正在调查为什么它是内部错误。

我们正在升级导出管道,新的导入管道存在一个错误,该错误不适用于当前管道导出的 Avro 文件。该修复程序应在几周内部署。之后,如果您将导出的文件导入到不存在的目标表或具有兼容模式的目标表,它应该可以工作。同时,导入您自己的 Avro 文件应该可以工作。也可以不导入直接在GCS上查询。

【讨论】:

总结:BigQuery 有一个错误:如果目标表存在,则使用 Avro 格式的插入作业不起作用,但会出现内部错误。解决方法是使用 createDisposition CREATE_IF_NEEDED 并且不要在那里放置表格。我验证了这项工作。【参考方案2】:

这里的 AVRO 阅读器的错误映射存在问题。错误应该是这样的:“参考架构与现有数据不同:缺少必填字段 'api_key'”

查看您的加载作业配置,它包含必填字段。听起来您尝试加载的某些数据没有指定这些必填字段,因此操作失败。

我建议避免使用必填字段。

【讨论】:

我正在从表中提取并加载到 same 表中。怎么会有模式差异?这是一个新的提取作业 ID (bqjob_r5f53dd0ed50e561d_000001543e21186f_1) 和相应的加载作业 ID (bqjob_r8db14d5e82c011d_000001543e21e8e0_1)。我还下载了提取文件并检查了每一行。它们都包含字段api_key。在 Java 程序中,我设法通过制作一个包含一个 NULLABLE 列 (STRING) 的简单表来取得进展。如果我向该表加载一行,则只有一行,但值为 null。【参考方案3】:

因此,BigQuery 中存在一个错误:如果目标表存在,则使用 Avro 格式的插入作业不起作用,但会出现内部错误。解决方法是使用createDispositionCREATE_IF_NEEDED,而不是那里有预先存在的表。我验证了这行得通。

Hua Zung 的评论说这个 bug 将在“修复应该在几周内部署”中修复。不用说应该在某个地方记录实时系统中现有的主要错误。

在更新系统时,我真的建议改进 Avro 文档。现在没有提到 Avro 模式应该是什么样的(类型 record,名称 root 和具有列(?)的字段数组),甚至没有提到 Avro 文件中的每条记录都映射到目标表(很明显,但应该提及)。此外,没有记录架构不匹配会发生什么。

感谢您的帮助,我现在将切换到 Avro 格式。它比 CSV 好多了。

【讨论】:

感谢您的建议。我会转发给我们的技术作家。

以上是关于将 Avro 文件加载到 BigQuery 失败并出现内部错误的主要内容,如果未能解决你的问题,请参考以下文章

如何将 AVRO 文件中的整数值加载到 bigquery 中的日期列?

推断 BigQuery 表加载的 avro 架构

通过 CLI 将存储桶中的 AVRO 加载到具有日期分区的 BigQuery 中

将 avro 十进制数据加载到 BigQuery 中?

从 AVRO 加载到 BigQuery - 在目标表中指定十进制类型

如何从具有 DATE 列的 BigQuery 表中导出 AVRO 文件并将其再次加载到 BigQuery