分区 table 上的 BigQuery DML,在可空记录中具有嵌套的必填字段
BigQuery DML on partitioned table with nested required fields in nullable records
我们在 BigQuery 中有一个数据湖,它是一个每日分区的 table(每天有几个 TB 的数据)。 table 应该有一个基于由多个字段组成的复合键的唯一标识符。
时不时地,我们必须对历史数据进行修改,我们使用 DML 来处理这些数据。修改的目标是有一种修改数据的简单方法,即成本高效且 atomic.
由于我们的 table 具有的模式,挑战出现了。我将用一个例子来说明。请注意,此 table 未分区,尽管这对于图示来说无关紧要,只是为了成本。最终解决方案应利用 table 已分区这一事实。
假设我们有一个 table,具有以下架构:
以及以下数据:
假设 fruit.color
应该用 DML 语句更改。请注意,fruit
是 nullable 记录,而 fruit.type
是 required.
可以使用 UPDATE
或 MERGE
查询来执行 DML。
使用UPDATE
#standardSQL
UPDATE `test_dataset.fruity_table`
SET
fruit.color = 'unknown'
WHERE id in ('1', '2')
不幸的是,UPDATE
语句没有条件更新字段的选项。这是必需的,因为上面的查询因 Required field fruit.type cannot be null; error in writing field fruit
而失败。可以为此使用子查询,但在我们的架构中,可空记录中的必填字段非常常见。因此,我们必须执行多个更新语句,这会破坏原子要求。
使用MERGE
#standardSQL
MERGE `test_dataset.fruity_table` t
USING `test_dataset.fruity_table` s
ON t.id = s.id
WHEN MATCHED AND t.fruit IS NOT NULL
THEN UPDATE SET fruit.color = 'unknown'
WHEN MATCHED AND t.fruit IS NULL
THEN -- do nothing, maybe update some other fields that need to be changed
对于 MERGE
语句,不幸的是我们不得不处理 BigQuery table 中存在重复项的事实。这是 MERGE
语句无法处理的。它因 UPDATE/MERGE must match at most one source row for each target row
.
而失败
如您所见,我们需要 MERGE
查询的粒度,以及 UPDATE
查询的灵活性。如果 MERGE
只更新所有匹配的记录,这会起作用。
关于如何解决这个问题有什么想法吗?也许是一种完全不同的方法?
使用 UPDATE,而不是 SET'ing fruit.color,SET 水果 - 类似于您在 MERGE 中的做法。您只需要将 MERGE 中的选项表达为单个表达式设置水果,或者为 NULL 或带有 non-NULL 必填字段的内容:
update test_dataset.fruity_table
SET fruit = IF(fruit IS NOT NULL, STRUCT('unknown', fruit.type), NULL)
where id = '3'
我们在 BigQuery 中有一个数据湖,它是一个每日分区的 table(每天有几个 TB 的数据)。 table 应该有一个基于由多个字段组成的复合键的唯一标识符。
时不时地,我们必须对历史数据进行修改,我们使用 DML 来处理这些数据。修改的目标是有一种修改数据的简单方法,即成本高效且 atomic.
由于我们的 table 具有的模式,挑战出现了。我将用一个例子来说明。请注意,此 table 未分区,尽管这对于图示来说无关紧要,只是为了成本。最终解决方案应利用 table 已分区这一事实。
假设我们有一个 table,具有以下架构:
以及以下数据:
假设 fruit.color
应该用 DML 语句更改。请注意,fruit
是 nullable 记录,而 fruit.type
是 required.
可以使用 UPDATE
或 MERGE
查询来执行 DML。
使用UPDATE
#standardSQL
UPDATE `test_dataset.fruity_table`
SET
fruit.color = 'unknown'
WHERE id in ('1', '2')
不幸的是,UPDATE
语句没有条件更新字段的选项。这是必需的,因为上面的查询因 Required field fruit.type cannot be null; error in writing field fruit
而失败。可以为此使用子查询,但在我们的架构中,可空记录中的必填字段非常常见。因此,我们必须执行多个更新语句,这会破坏原子要求。
使用MERGE
#standardSQL
MERGE `test_dataset.fruity_table` t
USING `test_dataset.fruity_table` s
ON t.id = s.id
WHEN MATCHED AND t.fruit IS NOT NULL
THEN UPDATE SET fruit.color = 'unknown'
WHEN MATCHED AND t.fruit IS NULL
THEN -- do nothing, maybe update some other fields that need to be changed
对于 MERGE
语句,不幸的是我们不得不处理 BigQuery table 中存在重复项的事实。这是 MERGE
语句无法处理的。它因 UPDATE/MERGE must match at most one source row for each target row
.
如您所见,我们需要 MERGE
查询的粒度,以及 UPDATE
查询的灵活性。如果 MERGE
只更新所有匹配的记录,这会起作用。
关于如何解决这个问题有什么想法吗?也许是一种完全不同的方法?
使用 UPDATE,而不是 SET'ing fruit.color,SET 水果 - 类似于您在 MERGE 中的做法。您只需要将 MERGE 中的选项表达为单个表达式设置水果,或者为 NULL 或带有 non-NULL 必填字段的内容:
update test_dataset.fruity_table
SET fruit = IF(fruit IS NOT NULL, STRUCT('unknown', fruit.type), NULL)
where id = '3'