对于我的用例,我正在使用源处的唯一键可识别的数据分解为n个(不确定的)数量的目标条目,这些条目已加载到BigQuery表中以进行分析。
构建此ETL以使用Mongo最近的变更流功能我想删除BigQuery中的所有条目,然后自动加载新条目。
探索BigQuery DML,我看到支持MERGE操作,但只能使用WHEN MATCHED THEN DELETE
或WHEN MATCHED THEN UPDATE
。
我对何时匹配然后删除并按照INSERT 操作感兴趣。
我如何在BigQuery中实现这样的ETL,同时在数据可用性和正确性方面保持原子性或最终一致性。
编辑1:我想提供一个具体的例子来详细说明。
我在此数据集上具有的最小唯一性粒度为user_id
。行不是唯一可识别的。
示例
从mongo更改流收到的更新的用户对象:
user={_id: "3", name="max", registered="2018-07-05" q=["a", "b", "c"]}
当前BigQuery.user_q保持
| user_id | q |
...
| 3 | a |
| 3 | b |
...
转换代码将修改后的用户对象加载到BigQuery.user_q_incoming
| user_id | q |
| 3 | a |
| 3 | b |
| 3 | c |
在user_q
和user_q_incoming
之间合并:
user_q
中属于user_id 3
的2行被删除user_q_incoming
中,属于user_id 3
的...
中的其余数据(user_q
)保留不变,未修改。BigQuery.user_q保存
| user_id | q |
...
| 3 | a |
| 3 | b |
| 3 | c |
...
例如,用户可以从个人资料中删除问题。将其余的行保留为q=["a", "c"]
。我还需要将其转换为BigQuery世界视图。
答案 0 :(得分:2)
BigQuery DML支持INSERT
MERGE语句是DML语句,可以将INSERT,UPDATE和DELETE操作组合为单个语句,并自动执行操作。
例如
MERGE dataset.Inventory T
USING dataset.NewArrivals S
ON FALSE
WHEN NOT MATCHED AND product LIKE '%washer%' THEN
INSERT (product, quantity) VALUES(product, quantity)
WHEN NOT MATCHED BY SOURCE AND product LIKE '%washer%' THEN
DELETE
因此,您最好使用ETL
根据添加到问题的更多具体细节进行编辑
好的,我知道-我认为在这种情况下,MERGE将不适用,因为只能对NOT MATCH子句执行INSERT。有人可能会想出在这种情况下如何使MERGE起作用的方法,但与此同时,下面的解决方案可以实现您想要实现的目标-我认为是:o)
CREATE OR REPLACE TABLE `project.dataset.user_q` (user_id INT64, q STRING) AS
SELECT * FROM `project.dataset.user_q`
WHERE NOT user_id IN (SELECT DISTINCT user_id FROM `project.dataset.user_q_incoming`)
UNION ALL
SELECT * FROM `project.dataset.user_q_incoming`
WHERE user_id IN (SELECT DISTINCT user_id FROM `project.dataset.user_q`)
答案 1 :(得分:1)
有一个类似的问题和一个解决方法,可以使MERGE(https://issuetracker.google.com/issues/35905927#comment9)工作。
基本上,以下操作应该有效,
MERGE `project.dataset.user_q` T
USING (
SELECT *, false AS is_insert FROM `project.dataset.user_q_incoming`
UNION ALL
SELECT *, true AS is_insert FROM `project.dataset.user_q_incoming`
) S
ON T.user_id = S.user_id and NOT is_insert
WHEN MATCHED THEN
DELETE
WHEN NOT MATCHED AND is_insert THEN
INSERT(user_id, q) VALUES(user_id, q)
理想情况下,以下是您所需要的,但尚不支持。
MERGE `project.dataset.user_q`
USING `project.dataset.user_q_incoming`
ON FALSE
WHEN NOT MATCHED BY TARGET THEN
INSERT(user_id, q) VALUES(user_id, q)
WHEN NOT MATCHED BY SOURCE AND user_id in (SELECT user_id FROM `project.dataset.user_q_incoming`) THEN
DELETE