使用流式 API 更新新列后无法向 BigQuery 表插入新值
Posted
技术标签:
【中文标题】使用流式 API 更新新列后无法向 BigQuery 表插入新值【英文标题】:Cannot insert new value to BigQuery table after updating with new column using streaming API 【发布时间】:2014-08-13 06:06:05 【问题描述】:我的 bigquery 表出现了一些奇怪的行为,我刚刚向表中添加了一个新列,它在界面上看起来不错,并通过 api 获取架构。
但是在向新列添加值时出现以下错误:
"insertErrors" : [
"errors" : [
"message" : "no such field",
"reason" : "invalid"
],
"index" : 0
],
"kind" : "bigquery#tableDataInsertAllResponse"
我正在使用 java 客户端和流 API,我唯一添加的是:
tableRow.set("server_timestamp", 0)
没有这条线它可以正常工作:(
你有没有发现它有什么问题(列名是server_timestamp,它被定义为一个INTEGER)
【问题讨论】:
它在几个小时后开始工作......这是预期的吗? 【参考方案1】:自 2014 年 8 月最初回答此问题以来,BigQuery 的流式传输系统已经看到重大更新,因此更新此答案。
BigQuery 的流式传输系统会将表架构缓存长达 2 分钟。当您将字段添加到架构中,然后立即将新行流式传输到表中时,您可能会遇到此错误。
避免此错误的最佳方法是在修改表后将带有新字段的流式行延迟 2 分钟。
如果这不可能,您还有其他一些选择:
使用ignoreUnknownValues
选项。此标志将告诉插入操作忽略未知字段,并仅接受它识别的那些字段。设置此标志允许您立即开始使用新字段流式传输记录,同时避免在 2 分钟窗口期间出现“没有此类字段”错误——但请注意,新字段值将被静默删除,直到缓存表架构更新!
使用skipInvalidRows
选项。此标志将告诉插入操作插入尽可能多的行,而不是在检测到单个无效行时使整个操作失败。如果只有部分数据包含新字段,则此选项很有用,因为您可以继续使用旧格式插入行,并单独决定如何处理失败的行(使用 ignoreUnknownValues
或等待 2 分钟窗口通过)。
如果您必须捕获所有值并且不能等待 2 分钟,您可以使用更新的架构创建一个新表并流式传输到该表。这种方法的缺点是您需要管理由这种方法生成的多个表。请注意,您可以使用TABLE_QUERY
方便地查询这些表,并且可以运行定期清理查询(或表副本)以将数据合并到一个表中。
历史记录:此答案的先前版本建议用户停止流式传输,将现有数据移动到另一个表,重新创建流式传输表,然后重新启动流式传输。但是,由于这种方法的复杂性和架构缓存的缩短窗口,BigQuery 团队不再推荐这种方法。
【讨论】:
应该注意这不是一个真正的 SLA(当然,除非它开始出现在状态页面上)。 code.google.com/p/google-bigquery/issues/detail?id=771 真的不是2分钟,不是吗?我等了2个小时。我可以在 Web UI 中看到正确的架构,但插入 VIA API 仍然会引发此错误。重新加载表 (googlecloudplatform.github.io/google-cloud-php/#/docs/v0.20.1/…) 也无济于事。在 BigQuery 自行刷新之前,谁能承受丢失数小时的数据? 这个答案仍然准确吗?等待几分钟似乎对我不起作用。架构更新通常需要多长时间才能传播? 这里也一样。新的表架构在 UI 中可见,但在等待超过 2 分钟后流式插入仍然失败。【参考方案2】:我遇到了这个错误。事实证明,我正在构建插入对象,就像我处于“原始”模式但忘记设置标志 raw: true
一样。这导致 bigQuery 获取我的插入数据并将其再次嵌套在 json:
节点下。
换句话说,我是这样做的:
table.insert(
insertId: 123,
json:
col1: '1',
col2: '2',
);
什么时候我应该这样做:
table.insert(
insertId: 123,
json:
col1: '1',
col2: '2',
, raw: true);
node bigquery 库没有意识到它已经处于raw
模式,然后试图插入:
insertId: '<generated value>',
json:
insertId: 123,
json:
col1: '1',
col2: '2',
所以在我的例子中,错误是指插入期望我的架构中有 2 列(insertId 和 json)。
【讨论】:
以上是关于使用流式 API 更新新列后无法向 BigQuery 表插入新值的主要内容,如果未能解决你的问题,请参考以下文章
BigQuery:使用 python BQ API 向现有表添加新列
使用 ALTER 添加新列后,数据错误地加载到 Hive 分区表中