我使用Python客户端库在BigQuery表中加载数据。我需要更新这些表中的一些更改的行。但我无法弄清楚如何正确更新它们?我想要一些类似的UPSERT
函数 - 只在不存在时插入行,否则 - 更新现有行。
在表中使用带校验和的特殊字段(并在加载过程中比较总和)是否是正确的方法?如果有一个好主意,如何用Python客户端解决这个问题? (据我所知,它无法更新现有数据)
请解释一下,最佳做法是什么?
答案 0 :(得分:11)
BigQuery不直接支持UPSERT
,但如果您真的需要它,您可以一个接一个地使用UPDATE
和INSERT
来实现相同目标。见下面简化的例子
假设您有两个表格,一个用于保存您的数据(yourproject.yourdadtaset.table_data
),另一个用于包含您要应用于第一个表格的更改的yourproject.yourdadtaset.table_changes
现在,下面的查询一个接一个地执行操作:
更新查询:
#standardSQL
UPDATE `yourproject.yourdadtaset.table_data` t
SET t.value = s.value
FROM `yourproject.yourdadtaset.table_changes` s
WHERE t.id = s.id
现在 - 插入查询
#standardSQL
INSERT `yourproject.yourdadtaset.table_data` (id, value)
SELECT id, value
FROM `yourproject.yourdadtaset.table_changes`
WHERE NOT id IN (SELECT id FROM `yourproject.yourdadtaset.table_data`)
希望上面的例子简单明了,所以你可以在你的案例中应用它
答案 1 :(得分:9)
BigQuery是设计附加的首选。这意味着您最好从表中的同一实体中获取重复行,并将查询写入以始终读取最近的行。
在BQ中无法按事务表中的知道更新行。每个表每天只有100个更新。这非常有限,他们的目的完全不同。
由于BQ用作数据湖,因此您应该在每次用户例如:更新其个人资料时流式传输新行。您将最终为同一用户提供20次保存20行。稍后,您可以通过删除重复数据将表重新打造为具有唯一行。
答案 2 :(得分:8)
BigQuery现在支持MERGE
,它可以在一个原子操作(即INSERT
)中结合使用UPDATE
和UPSERT
。
使用Mikhail的示例表,它看起来像:
MERGE merge_example.table_data T
USING merge_example.table_changes S
ON T.id = S.id
WHEN MATCHED THEN
UPDATE SET value = s.value
WHEN NOT MATCHED THEN
INSERT (id, value) VALUES(id, value)
请参见here。
答案 3 :(得分:3)
为此,我可能迟到了,但是您可以使用Dataflow / Apache Beam在BigQuery中执行upsert。您可以执行CoGroupByKey以从两个数据源(一个是目标表)中获取共享公用密钥的值,并更新从目标BQ表中读取的数据。最后以截断加载模式加载数据。希望这会有所帮助。
这样,您可以避免BigQuery中的所有配额限制,并在Dataflow中进行所有更新。