如果我在流式传输之前先删除表并创建表,Google BigQuery Streaming 有时会失败

Posted

技术标签:

【中文标题】如果我在流式传输之前先删除表并创建表,Google BigQuery Streaming 有时会失败【英文标题】:Google BigQuery Streaming failed sometimes if I do delete table and create table first, before streaming 【发布时间】:2018-08-23 23:51:24 【问题描述】:

我正在将数据流式传输到 BigQuery 表中。

删除旧表 创建具有相同名称和相同架构的新表 将数据流式传输到新表中

我之前做过很多次,效果很好。但最近我开始发现上述方法不起作用。

流式传输完成后(未报告错误),我查询表,有时它可以工作。有时,我有空桌子。 (相同的脚本,相同的数据,运行多次,结果不同。有时有效,有时无效。)

更神秘的是,当我流式传输大量数据时,它似乎在大多数情况下都有效。但是当我流式传输少量数据时,大多数时候它都失败了。

但如果我只是这样做

创建一个新表 将数据流式传输到新表中

它总是有效的。

我在 Google Apps Scrip 和 php Google Cloud Client Library for BigQuery 中都试过这个。我有同样的问题。

所以我在 Google Apps 脚本中尝试了这个

删除旧表 睡眠 10 秒,所以删除工作应该完成 创建具有相同名称和相同架构的新表 睡眠 10 秒,创建作业应该完成 将数据流式传输到新表中

它仍然给我同样的问题。

但是没有错误报告或记录。

其他信息:

我又试了一次。

如果我等到流缓冲区为空,然后运行脚本。结果总是正确的。新数据成功流入新表。

但是如果我在之前运行之后立即运行脚本,那么结果是空的。数据不会流式传输到新表中。

所以当我在流缓冲区不为空时“删除旧表并创建新表”时似乎发生错误。

但是根据这个帖子的回答,BigQuery Stream and Delete while streaming buffer is not empty?,

旧表和新表(即使它们具有相同的名称和相同的架构),它们具有两个不同的“对象ID”。它们实际上是两个不同的表。删除旧表后,流缓冲区中的旧记录也会被删除。流缓冲区是否为空,应该不会影响我接下来的步骤,创建一个新表并将新数据流式传输到新表中。

另一方面,如果我尝试“截断旧表”而不是“删除旧表并创建新表”,而流缓冲区中可能仍有数据,则“DML 语句无法修改仍在流缓冲区”,因此“截断旧表”会失败。

简单来说,在这个用例中,

我无法截断旧表,因为 Steam 缓冲区可能不是空的。 我应该“删除旧表并创建新表,然后将数据流式传输到新表”。但这似乎是我当前问题的根源,我的新数据无法流式传输到新表(即使新表具有新的对象 ID,也不应该受到我只是删除旧表的影响)

【问题讨论】:

您之前在***.com/q/48331407/6253347 中提出了类似的问题,Graham 分享了@98​​7654323@,这解释了您所看到的。您应该截断表而不是使用相同的架构删除和重新创建... @ElliottBrossard,我对来自 ***.com/q/48331407/6253347 的答案的理解是相反的。我想我应该删除旧表并创建一个新表。因为对象id不同,所以实际上是两张新表。 “1)正确。“对象ID”不同,剩余记录将被丢弃。 - 所以如果我删除旧表,旧表缓冲中的剩余记录也将被删除。他们不会流入新表。然后我会将新数据流式传输到新表,新表具有新的对象ID,因此新记录将流式传输到新表。 @ElliottBrossard 2) 有点正确。 DML 语句不能修改仍在流缓冲区中的数据。但是,如果该语句尝试触及仍在流缓冲区中的行,则该语句将失败。”如果我截断表,则有些记录可能仍在流缓冲区中,当我截断表时,该语句将失败。所以我的理解是我应该删除旧表并创建一个新表,而不是截断旧表。 【参考方案1】:

避免在流式传输时截断和重新创建表。

来自官方文档:

https://cloud.google.com/bigquery/troubleshooting-errors#streaming

表创建/删除 - 流式传输到不存在的表将返回 notFound 响应的变体。随后的流式插入可能不会立即识别作为响应创建表。类似地,删除和/或重新创建表可能会在一段时间内创建流式插入有效地传递到旧表并且不会出现在新创建的表中。

表截断 - 截断表的数据(例如,通过使用 WRITE_TRUNCATE 的 writeDisposition 的查询作业)可能同样会导致一致性期间的后续插入被删除。

为避免丢失数据:创建一个具有不同名称的新表。

【讨论】:

“创建响应的表可能不会立即被后续的流式插入识别。”,因此除了“为了避免丢失数据:创建一个具有不同名称的新表。”在进行流式传输之前,我们需要确认创建表的工作已完成或新表存在,对吗?但是通常创建表很快就完成了,sleep几秒钟就几乎可以保证它完成了。 创建一个不同名称的新表是不合理的。我们使用这些表格进行报告。如果我们不断更改表的名称,我们究竟应该如何保持数据最新?对于这样的问题,这是一个糟糕的解决方案。即使您不使用它进行报告,如果您不断更改表名,您将如何保持数据完整性?【参考方案2】:

我在我的另一个线程中发布了有关流式传输到 BigQuery 的帖子。现在,作为一项规则,如果可以,我会尽量避免流式传输。

将数据加载到 Cloud Storage 然后将数据从 Cloud Storage 加载到 BigQuery

这将解决许多与流媒体相关的问题。

【讨论】:

以上是关于如果我在流式传输之前先删除表并创建表,Google BigQuery Streaming 有时会失败的主要内容,如果未能解决你的问题,请参考以下文章

将 BigQuery 表流式传输到 Google Pub/Sub

为流式插入自动创建 BQ 表

如何使用 Elasticbeanstalk 在亚马逊 RDS 中删除表并重新创建?

从 Google App Engine 流式传输音频

VBA excel添加新工作表并删除原来的

GoogleApiException:流式传输到 BigQuery 时,Google.Apis.Requests.RequestError 后端错误 [500]