使用流API更新新列后,无法向BigQuery表插入新值

时间:2014-08-13 06:06:06

标签: google-bigquery

我在我的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)

2 个答案:

答案 0 :(得分:9)

更新此答案,因为BigQuery的流媒体系统自2014年8月以来已经看到重大更新,此时此问题最初得到解答。


BigQuery的流式传输系统将表模式缓存最多2分钟。向架构添加字段然后立即将新行流式传输到表时,可能会遇到此错误。

避免此错误的最佳方法是在修改表格后使用新字段延迟流式行2分钟。

如果不可能,您还有其他一些选择:

  1. 使用ignoreUnknownValues选项。此标志将告诉插入操作忽略未知字段,并仅接受它识别的那些字段。设置此标志允许您立即使用新字段开始流式传输记录,同时避免在2分钟窗口期间出现“无此字段”错误 - 但请注意,新字段值将以静默方式删除,直到缓存的表架构更新为止!

  2. 使用skipInvalidRows选项。此标志将告诉插入操作尽可能多地插入行,而不是在检测到单个无效行时使整个操作失败。如果只有部分数据包含新字段,则此选项很有用,因为您可以继续使用旧格式插入行,并分别决定如何处理失败的行(使用ignoreUnknownValues或等待2分钟窗口通过)。

  3. 如果必须捕获所有值并且不能等待2分钟,则可以使用更新的模式创建新表并将流传输到该表。这种方法的缺点是您需要管理这种方法生成的多个表。请注意,您可以使用TABLE_QUERY方便地查询这些表,并且可以运行定期清理查询(或表副本)以将数据合并到单个表中。

    历史记录:此答案的先前版本建议用户停止流式传输,将现有数据移至另一个表,重新创建流式表,然后重新启动流式传输。但是,由于此方法的复杂性和架构缓存的缩短窗口,BigQuery团队不再推荐这种方法。

答案 1 :(得分: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});

节点bigquery库没有意识到它已经处于raw模式,然后尝试插入它:

{
    insertId: '<generated value>',
    json: {
        insertId: 123,
        json: {
            col1: '1',
            col2: '2',
     }
}

所以在我的情况下,错误指的是插件期望我的架构中有2列(insertId和json)。