Раздел 26 · Data Engineering

Snapshots: история изменений (SCD type 2)

junior~15 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

Отто разбирает весну: «Почему у Уралмаша в апреле подскочили опоздания?» Ты открываешь отчёт «курьеры по зонам» и видишь странное. Отчёт берёт зону курьера из couriers. Курьер Олег сегодня числится в Уралмаше, и все его весенние доставки отчёт записывает Уралмашу, хотя в апреле Олег работал в Центре. Таблица couriers знает только, где курьер сейчас. Когда его перевели, старое значение zone_id просто перезаписали. Истории нет, и вопрос Отто без неё не решить.

Штампы в паспорте

В паспорте не стирают старую прописку, когда человек переезжает. Старый штамп остаётся, на нём пишут дату выписки, а рядом ставят новый. Можно в любой момент сказать, где человек жил в марте прошлого года.

Снапшот в dbt ведёт такую историю для строк таблицы: старую версию не перезаписывает, а закрывает датой, и рядом дописывает новую.

SCD type 2

Такой способ хранения истории называют SCD type 2: медленно меняющееся измерение второго типа. Справочник курьеров меняется редко, но меняется. Первый тип просто перезаписывает строку, как сейчас делает couriers. Второй хранит все версии.

Снапшот в dbt добавляет к копии таблицы четыре служебные колонки:

КолонкаЧто в ней
dbt_valid_fromс какого момента версия действует
dbt_valid_toдо какого момента; null у текущей версии
dbt_updated_atмомент, по которому версия получена
dbt_scd_idуникальный ключ версии, хэш от ключа и времени

Где курьер работал 15 апреля, отвечает запрос с условием dbt_valid_from <= '2026-04-15' and (dbt_valid_to > '2026-04-15' or dbt_valid_to is null).

Снапшот в YAML

В dbt 1.12 снапшот описывают в YAML в папке snapshots/:

# snapshots/couriers.yml
snapshots:
  - name: couriers_snapshot
    relation: source('raw', 'couriers')
    config:
      unique_key: id
      strategy: check
      check_cols: ["zone_id", "transport"]

relation говорит, с какой таблицы снимать историю. unique_key это ключ, по которому dbt узнаёт «ту же самую» строку в новом запуске. В старых проектах и статьях снапшот пишут SQL-файлом с блоком {% snapshot %}. Так тоже работает, но новый способ короче.

урок из курса

Урок из курса «Data Engineering». Курс покупается один раз и остаётся навсегда: 500 ₽.

Оплата пока не подключена: премиум и курсы открываются промокодом.