BigQuery DML для многораздельной таблицы с вложенными обязательными полями в обнуляемых записях - PullRequest
0 голосов
/ 27 июня 2019

У нас есть озеро данных в BigQuery, которое представляет собой ежедневную многораздельную таблицу (с несколькими ТБ данных / день). Таблица должна иметь уникальный идентификатор на основе составного ключа, состоящего из нескольких полей.

Время от времени нам приходится вносить изменения в исторические данные, к которым мы подходили, используя DML . Целью модификации является простой способ изменения данных, который является экономически эффективным и атомным .

Проблема возникает из-за схемы, которую имеет наша таблица. Я проиллюстрирую на примере. Обратите внимание, что эта таблица не разделена, хотя это не должно иметь значения для иллюстрации, только для затрат. Окончательное решение должно использовать тот факт, что таблица секционирована.

Предположим, у нас есть таблица со следующей схемой:

Table schema

И следующие данные:

Table data

Допустим, что 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 просто обновит все сопоставляемые записи, это сработает.

Есть идеи, как это решить? Может быть, совершенно другой подход?

1 Ответ

2 голосов
/ 27 июня 2019

Используйте UPDATE, а не SET'ing fruit.color, SET fruit - аналогично тому, как вы делаете это в MERGE. Вам просто нужно выразить опции, которые у вас есть в MERGE, в виде отдельного выражения, устанавливающего фрукт, либо в NULL, либо в чем-то с полем, отличным от NULL:

update test_dataset.fruity_table
SET fruit = IF(fruit IS NOT NULL, STRUCT('unknown', fruit.type), NULL) 
where id = '3'
...