Инкрементальная загрузка

Урок объясняет, как грузить только новые данные, а не всю таблицу каждый раз.

Инкрементальная загрузка — извлечение из источника только данных, изменившихся с прошлого запуска, по «водяному знаку» (watermark).

Зачем не грузить всё заново

Полная перезаливка (full load) проста, но не масштабируется: когда в источнике сто миллионов строк, читать их целиком каждый час невозможно. Инкрементальная загрузка забирает только новое — например, заказы с created_at больше последней обработанной даты. Это и есть водяной знак: метка «докуда мы дочитали».

full load:        каждый раз тащим ВСЕ 100 млн строк            (дорого)
incremental:      watermark = 2026-06-21 10:00
                  тащим только WHERE created_at > watermark     (дёшево)

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

Как работает под капотом

Источник на SQL: выбираем только записи новее водяного знака.

CREATE TABLE source_orders (id INTEGER PRIMARY KEY, created_at TEXT, amount INTEGER);
INSERT INTO source_orders VALUES
    (1,'2026-06-20',300), (2,'2026-06-21',500), (3,'2026-06-22',700);

-- watermark из прошлого запуска: 2026-06-21
SELECT id, created_at, amount
FROM source_orders
WHERE created_at > '2026-06-21'
ORDER BY created_at;

Логика обновления водяного знака на чистом Python: грузим новое и сдвигаем метку на максимум обработанного.

source = [
    {"id": 1, "ts": "2026-06-20"},
    {"id": 2, "ts": "2026-06-21"},
    {"id": 3, "ts": "2026-06-22"},
]
watermark = "2026-06-21"

new_rows = [r for r in source if r["ts"] > watermark]
print("Новых записей:", len(new_rows))
if new_rows:
    watermark = max(r["ts"] for r in new_rows)
print("Новый watermark:", watermark)

Вывод:

Новых записей: 1
Новый watermark: 2026-06-22

Водяной знак — это маленькое состояние, которое конвейер несёт от запуска к запуску. Его обычно хранят в таблице-метаданных, в переменной Airflow или прямо в имени последней загруженной партиции. Главное правило — обновлять watermark только после того, как новые данные успешно загружены в приёмник. Если сдвинуть метку раньше и загрузка упадёт, эти записи будут потеряны навсегда: следующий запуск решит, что они уже обработаны.

Полная и инкрементальная — когда что

Full loadIncremental
маленькие справочникибольшие журналы событий
просто, всегда консистентнодёшево, но сложнее

Частые ошибки

  • Брать >= вместо > по водяному знаку. Граничные записи обработаются дважды; либо строго >, либо upsert для защиты от дублей.
  • Опоздавшие записи. Если событие пришло в источник с задержкой и его дата меньше watermark, инкремент его пропустит — нужен запас или окно перезахвата.
  • Хранить watermark в памяти задачи. Его место — во внешнем состоянии (таблица, переменная Airflow), иначе он теряется между запусками.

Итог

  • Инкрементальная загрузка тащит только новые данные по водяному знаку.
  • Это масштабируется на большие источники в отличие от полной перезаливки.
  • Watermark хранят во внешнем состоянии, а захват делают идемпотентным.
Проверьте себя
1. Что такое водяной знак (watermark) при инкрементальной загрузке?
AЛоготип на данных
BМетка «докуда уже обработано», по которой берут только новые записи
CИмя таблицы-приёмника
DПароль к источнику
2. Почему инкрементальную загрузку предпочитают полной для больших источников?
AОна надёжнее во всех случаях
BОна тащит только новые данные, а не сто миллионов строк каждый раз
CОна не требует водяного знака
DОна работает только с CSV