使用流式 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 表插入新值的主要内容,如果未能解决你的问题,请参考以下文章

Spark dataFrame在更新其列后显示时间过长

BigQuery:使用 python BQ API 向现有表添加新列

使用 ALTER 添加新列后,数据错误地加载到 Hive 分区表中

在 IMPALA/HIVE 中添加带有 SELECT 的新列后,旧表数据变为 NULL

Mysql下在某一列后即表的某一位置添加新列的sql语句

SQL给表增加一个新列后,明明有列 查询时说这个列无效