"更新"的良好实践

时间:2017-09-03 02:09:17

标签: google-bigquery

我有一个包含数据的CSV:

 ID, Name, Address, Date
 1 , Paul, Fake 123,2017-01-01

我将该文件上传到新表(即:"用户")

几个月后,我收到了一张带有该表的插入和更新的CSV。即。

 ID, Name, Address, Date
 1 , Paul, Fake 999,2017-06-01
 2 , Joe , Foo 123 ,2017-06-01
 ...

如果它是一个常见的SQL数据库,我做了一个Upsert(比如Mysql中的Replace)。但是在BigQuery中执行此操作的最佳模式是什么?更新的DML配额限制为每个表96个,对此来说太小了:(。

我在"交易"表,和#34; final"表

当我有一个新文件时,我可以上传到Transactional表。之后,我可以执行查询,获取每个" ID"的最后一个值,并将该数据放入" Final"表。显然,查询有选项" writeDisposition:WRITE_TRUNCATE"删除旧数据。

我认为这是一个混乱的解决方案,但我找不到更好的方法。有人知道怎么做得更好吗?有任何地方可以阅读"设计模式"对于BigQuery?

1 个答案:

答案 0 :(得分:1)

很少有笔记,

  • 我假设数据的变化相对于目标数据足够大以覆盖目标表。例如,如果对于具有十亿条记录的目标表有几百条更改记录,则不希望遵循此方法。
  • 此外,查询可能需要对分区表进行一些更改。
  • 作为副作用,这将从目标表中删除任何重复记录。因此,您需要仔细选择用于标识记录更改的列。

使用联接和登陆表:

让我们的调用表包含需要合并到目标表的更改数据源。

SELECT SRC.Id as Id,
       SRC.Name as Name,
       SRC.Address as Address,
       SRC.Date as Date
FROM SourceTable SRC 
     LEFT OUTER JOIN TargetTable TGT
USING (Id)
WHERE TGT.Id IS NULL

UNION DISTINCT

SELECT CASE WHEN (SRC.Id IS NOT NULL AND SRC.Name IS NOT NULL AND SRC.Address IS NOT NULL AND SRC.Date IS NOT NULL) THEN SRC.Id ELSE TGT.Id END AS Id,
       CASE WHEN (SRC.Id IS NOT NULL AND SRC.Name IS NOT NULL AND SRC.Address IS NOT NULL AND SRC.Date IS NOT NULL) THEN SRC.Name ELSE TGT.Name END AS Name,
       CASE WHEN (SRC.Id IS NOT NULL AND SRC.Name IS NOT NULL AND SRC.Address IS NOT NULL AND SRC.Date IS NOT NULL) THEN SRC.Address ELSE TGT.Address END AS Address,
       CASE WHEN (SRC.Id IS NOT NULL AND SRC.Name IS NOT NULL AND SRC.Address IS NOT NULL AND SRC.Date IS NOT NULL) THEN SRC.Date ELSE TGT.Date END AS Date
FROM SourceTable SRC 
     RIGHT OUTER JOIN TargetTable TGT
USING (Id) 

现在,您可以在目标表上使用WRITE_TRUNCATE运行上述查询。 我没有测试过这个特定的查询,但方法很好。可以通过Bigquery中的一点点编码或UDF来减少查询的复杂性。性能在很大程度上取决于变更数据的大小和性质。

我希望这会有所帮助。