首页 > 解决方案 > BigQuery MERGE 语句计费的字节数超过编辑器显示的字节数

问题描述

我有一个非常大的(3.5B 记录)表,我想使用MERGEBigQuery 中的语句更新/插入(upsert)。源表是一个暂存表,只包含新数据,我需要检查目标表中是否有对应ID的记录,如果是则更新行,否则插入。

目标表由一个名为 的整数字段进行分区,并在另一个名为 的整数字段IdParent上完成匹配。我的合并语句/脚本如下所示:IdParentIdChild

declare parentList array<int64>;

set parentList = array(select distinct IdParent from dataset.Staging);

merge into dataset.Target t
using dataset.Staging s
on
  -- target is partitioned by IdParent, do this for partition pruning
  t.IdParent in unnest(parentList)
  and t.IdParent = s.IdParent
  and t.IdChild = s.IdChild
when matched and t.IdParent in unnest(parentList) then
  update
    set t.Column1 = s.Column1,
    t.Column2 = s.Column2,
    ...<more columns>
when not matched and IdParent in unnest(parentList) then
  insert (<all the fields>)
  values (<all the fields)
;

所以我:

总大小dataset.Target约为 250GB。如果我将此脚本放在我的 BQ 编辑器中并删除所有内容,IdParent in unnest(parentList)那么它会在编辑器中显示 ~250GB 的账单(正如预期的那样,因为没有分区修剪)。如果我添加IdParent in unnest(parentList)后面的脚本,那么脚本与您在上面看到的完全一样,即尝试进行分区修剪,编辑器会显示 ~97MB 来计费。但是,当我查看查询结果时,我发现它实际计费约为 180GB:

不同的字节计费与编辑的估计

目标表也在被匹配的两个字段上进行聚类,我知道聚类的好处通常不会显示在编辑的估计中。但是,我的理解是,这只会使计费的字节更小……我想不出任何原因会发生这种情况。

这是一个 BQ 错误,还是我只是错过了什么?BigQuery 甚至没有说“脚本估计要处理 XX MB”,它说“这将处理 XX MB”,然后它处理得更多。

标签: google-cloud-platformgoogle-bigquery

解决方案


这很有趣。你所做的似乎完全正确。

似乎 BQ 查询计划器可以正确解释您的 SQL 并知道提供了分区修剪,但是当它执行时。它没有这样做。

尝试t.IdParent in unnest(parentList)从这两个when matched子句中删除以查看问题是否仍然存在,即

declare parentList array<int64>;

set parentList = array(select distinct IdParent from dataset.Staging);

merge into dataset.Target t
using dataset.Staging s
on
  -- target is partitioned by IdParent, do this for partition pruning
  t.IdParent in unnest(parentList)
  and t.IdParent = s.IdParent
  and t.IdChild = s.IdChild
when matched then
  update
    set t.Column1 = s.Column1,
    t.Column2 = s.Column2,
    ...<more columns>
when not matched then
  insert (<all the fields>)
  values (<all the fields)
;

如果无法解决,最好向 BigQuery 提交错误。


推荐阅读