Странное поведение потока в Snowflake

#snowflake-cloud-data-platform

#snowflake-cloud-data-platform

Вопрос:

Это касается потоков в таблице, которая опустошается, даже если я удостоверяюсь, что условие «включено» соответствует строке 1: 1 в исходной и целевой таблице.

Вот пример:

У меня есть поток в таблице, который имеет следующее состояние.

 backup, id, name, metadata$action
a, 1, Joe, DELETE
a, 2, Jane, DELETE
b, 1, Joe, INSERT
b, 2, Jane, INSERT
b, 3, Jake, INSERT
 

состояние перед слиянием

 backup, id, name
a,1,Joe
a,2,Jane
 

Но когда я вставляю его в целевую таблицу, используя оператор merge, используя

СЛИЯНИЕ С целью С ПОМОЩЬЮ stream на (target.id = stream.id и target.backup = stream.backup) ПРИ СОПОСТАВЛЕНИИ и stream.metadata$action = ‘DELETE’ ЗАТЕМ УДАЛИТЬ;

Это удаляет целевую таблицу, как и ожидалось, но полностью очищает ПОТОК, хотя условие ON гарантирует, что будут объединены только записи, соответствующие 1: 1, и условие указано как DELETE. Из-за этого я теряю все свои строки вставки в потоке.

Не могли бы вы, пожалуйста, сообщить мне, я делаю что-то не так или это ожидаемое поведение потока?

Ответ №1:

Вы пробовали использовать явный оператор транзакции?

Из документов Snowflake —

Чтобы обеспечить доступ нескольких операторов к одним и тем же записям изменений в потоке, окружите их явным оператором транзакции (BEGIN .. СОВЕРШИТЬ). Явная транзакция блокирует поток, так что обновления DML для исходной таблицы не передаются потоку до тех пор, пока транзакция не будет зафиксирована.

Источник: https://docs.snowflake.com/en/sql-reference/sql/create-stream.html#usage-notes

Или вы могли бы просто добавить еще один оператор для обработки ВСТАВКИ.

Например,

 when matched
    and source_table.metadata$action = 'INSERT'
    and source_table.metadata$isupdate then
    update set target_table.text = source_table.text
when matched
    and source_table.metadata$action = 'DELETE' then 
    delete
when not matched
    and source_table.metadata$action = 'INSERT' then 
    insert 
    (whatever you want to insert)
 

Ответ №2:

Это происходит потому, что оператор DML, который выбирает из потока, потребляет все данные изменения в потоке. Здесь оператор DML — DELETE . Возможно, вы захотите переместить данные потока в другую таблицу, а затем выполнить СЛИЯНИЕ.

Комментарии:

1. Привет, Раджиб, спасибо за ваш ответ. Я обновил вопрос, но нет смысла, чтобы поток полностью исчезал без обработки всех изменений. Я слежу за тем, чтобы исходная и целевая таблицы совпадали только в соотношении 1: 1. Даже тогда поток будет полностью удален.

Ответ №3:

Чтобы подробнее остановиться на ответе Раджиба.

Если вы понимаете, как физически работает поток Snowflake, становится понятно, почему он ведет себя таким образом (лично мне это поведение не нравится, но я вижу их логику).

В документации объясняется, что «сам поток не содержит никаких табличных данных. Поток сохраняет только смещение для исходной таблицы и возвращает записи CDC, используя историю версий для исходной таблицы «. (https://docs.snowflake.com/en/user-guide/streams.html#offset-storage )

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

Он не может учитывать, какие записи изменений были фактически возвращены запросом, потому что они могли быть не все последовательно. В исходной таблице могут быть записи изменений a, b и c, если ваш запрос выбирает только записи изменений a и c, поток все равно должен продвинуть указатель на изменение c (по сути, отбросив изменение b из потока).

В результате такого поведения мне пришлось изменить свой подход к работе с потоками, и теперь мы перемещаем все данные из потока в таблицу «хранения», прежде чем работать с ней.