【问题标题】:Overwriting multiple partitions bigquery覆盖多个分区 bigquery
【发布时间】:2020-05-31 11:05:24
【问题描述】:

假设我有一个表 t1,它在列 sdate 上进行日期分区

我有另一个表 t2,它也在列 pdate 上分区,其中一些分区中已经有数据(20200101 到 20200130)

现在,我想从t1 中的数据覆盖t2 中的几个分区(20200105 到 20200110)

我想在一个查询中完成,而不是每个分区一个查询。

选择查询:

SELECT sdate,
c1, c2

FROM `dataset.t1` where sdate between "2020-01-05" and "2020-01-10"

我见过一些例子,我们可以指定像t2$20200102 这样的目标表,但这只会覆盖一个分区。

我们如何编写插入语句来填充选定的分区

对插入查询的外观有什么想法吗?

【问题讨论】:

  • 是否有任何主键可以关联表 t1 和表 t2 中的行?
  • 不,没有任何钥匙。我唯一的目的是用来自 t2 的数据覆盖 t1 中的分区
  • 我问是因为要使用合并、更新和删除行,您需要一个主键来关联这两个表。否则,Guillem Xercavins 的答案是最好的选择。
  • 同意。我一直在寻找“原子”的东西。由于涉及多个步骤,如果任何步骤失败,我们最终可能会处于不一致的状态

标签: google-bigquery


【解决方案1】:

您可以在INSERT 语句中简单地使用SELECT sdate AS pdate

INSERT dataset.t2 (pdate, c1, c2) 
  SELECT sdate AS pdate, c1, c2
  FROM dataset.t1
  WHERE sdate BETWEEN "2020-01-05" and "2020-01-10"

当然,这会将行附加到每个目标分区,因此,如果要覆盖它们,可以先删除它们:

DELETE
  dataset.t2
WHERE
  pdate BETWEEN "2020-01-05" AND "2020-01-10"

显然,删除分区时应该小心。如果您只想用源表中的数据覆盖日期,可以添加额外的检查:

DELETE
  dataset.t2
WHERE
  pdate IN (
    SELECT sdate 
    FROM dataset.t1 
    WHERE sdate BETWEEN "2020-01-05" AND "2020-01-10")

您也可以考虑使用MERGE,但您需要考虑逐行匹配时会发生什么。

我用这个gist做了一些测试。

另一种选择是进行分段的SELECT 查询,将数据分成三个日期范围,然后通过UNION ALL 将它们组合在一起。

SELECT * FROM dataset.t2
WHERE pdate < "2020-01-05" OR pdate > "2020-01-10"
UNION ALL
SELECT * FROM dataset.t1
WHERE sdate BETWEEN "2020-01-05" AND "2020-01-10"

这需要使用WRITE_TRUNCATE 指定目标表并在单个作业中运行,但实际上必须重写整个表。

【讨论】:

  • 感谢您的回答,我正在寻找可以一步完成的事情。但这也有帮助
  • 另外,这个过程不是原子的,因为涉及多个步骤。
  • 为什么要使用 DML?它花费$$$。使用 'bq cp' cli 或 API 库并使用单个命令(每个分区)执行它。此操作是原子的,加载/复制不需要任何费用。文档:cloud.google.com/bigquery/docs/…
猜你喜欢
  • 2018-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-15
  • 1970-01-01
  • 1970-01-01
  • 2018-11-15
  • 2021-11-10
相关资源
最近更新 更多