У нас есть озеро данных в BigQuery, которое представляет собой ежедневную многораздельную таблицу (с несколькими ТБ данных / день). Таблица должна иметь уникальный идентификатор на основе составного ключа, состоящего из нескольких полей.
Время от времени нам приходится вносить изменения в исторические данные, к которым мы подходили, используя DML . Целью модификации является простой способ изменения данных, который является экономически эффективным и атомным .
Проблема возникает из-за схемы, которую имеет наша таблица. Я проиллюстрирую на примере. Обратите внимание, что эта таблица не разделена, хотя это не должно иметь значения для иллюстрации, только для затрат. Окончательное решение должно использовать тот факт, что таблица секционирована.
Предположим, у нас есть таблица со следующей схемой:
![Table schema](https://i.stack.imgur.com/eHizZ.png)
И следующие данные:
![Table data](https://i.stack.imgur.com/6fVmb.png)
Допустим, что fruit.color
следует изменить с помощью инструкции DML. Обратите внимание на тот факт, что fruit
является обнуляемой записью, а fruit.type
является обязательным .
DML может быть выполнен с использованием запроса UPDATE
или MERGE
.
Использование 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 есть дубликаты. Это то, что оператор MERGE
не может обработать. Сбой с UPDATE/MERGE must match at most one source row for each target row
.
Как видите, нам нужна гранулярность запроса MERGE
с гибкостью запроса UPDATE
. Если MERGE
просто обновит все сопоставляемые записи, это сработает.
Есть идеи, как это решить? Может быть, совершенно другой подход?