Что такое инкрементальная загрузка
Что проверяют
Умеете ли вы строить конвейер, который переживает перезапуск. Вопрос инженерный, а не терминологический: инкрементальная загрузка ломается тихо, и ценой ошибки становятся молча недосчитанные строки в витрине.
Как отвечать
Идея простая: грузим не всю таблицу, а только изменения с прошлого запуска. Механизмов два, и назвать стоит оба.
Загрузка по верхней границе: храним максимум колонки изменения (updated_at, растущий идентификатор, номер партиции) и берём то, что выше. Дёшево, но требует, чтобы источник честно обновлял эту колонку, и не видит удалений.
Захват изменений из журнала СУБД: логическая репликация в PostgreSQL, бинлог в MySQL. Приходят вставки, обновления и удаления как поток событий. Дороже в поддержке, зато полнее и не зависит от дисциплины разработчиков источника.
Обязательных свойств три: идемпотентность (повтор той же пачки не должен двоить строки, отсюда слияние по ключу вместо простой вставки), перекрытие окна назад, чтобы поймать опоздавшие записи, и регулярная полная сверка с источником.
MERGE INTO dwh.orders t USING stg.orders s ON t.id = s.id
WHEN MATCHED THEN UPDATE SET status = s.status, updated_at = s.updated_at
WHEN NOT MATCHED THEN INSERT VALUES (s.id, s.status, s.updated_at);Где спотыкаются
Говорят, что инкрементальная загрузка надёжнее полной. Наоборот: полная перезагрузка самовосстанавливается на каждом запуске, а инкремент копит расхождение, и без сверки о нём узнают от бизнеса.
Берут строго больше сохранённой границы и незаметно теряют строки. Записи с тем же значением времени, вставленные в источник во время прошлого чтения, не попадут уже никогда. Лечится перекрытием окна и дедупликацией по ключу, а не подбором знака сравнения.
Забывают про удаления и правки задним числом. Витрина продолжает хранить строки, которых в источнике давно нет, и суммы расходятся ровно на них. Выход либо в захвате изменений из журнала, либо в договорённости о мягком удалении флагом.