История изменений данных
Одна из основных концепций хранилищ данных - это хранение и обработка не только актуальных данных за текущий период, но и за предыдущие. Для владельцев и пользователей различных аналитических систем важно понимать как изменялись данные с течением времени. Для этих целей, как уже было отмечено ранее, в dbt™ реализована функциональность снэпшотов.
Напомню, что в отличие от моделей, которые всегда содержат только актуальное (текущее или последнее) состояние данных, снэпшоты позволяют вести версионность данных, то есть отслеживать изменение данных без потери предыдущих состояний.
Стандартные модели | Снэпшоты | |
Назначение | Преобразование данных на основе текущего состояния | Отслеживание изменений данных |
Материализация | Таблицы или представления с текущими данными | Таблицы истории, доступные только для добавления (append-only) |
Механизм формирования снэпшотов
Спэпшоты создаются при выполнении комады dbt snapshot. В момент запуска создается первый «слепок» данных, повторяющий структуру исходной таблицы, изменение которой планируется отслеживать, с дополнительными столбцами, включая dbt_valid_from и dbt_valid_to. При этом у всех записей dbt_valid_to будет иметь значение null.
При последующих запусках dbt™ проверяет, какие существующие записи изменились и были ли созданы новые. Если какая-то существующая запись изменилась, то dbt_valid_to обновит значение, а изменения запишутся в новую строку со значением dbt_valid_to = null. Новая запись, которой ранее не было тоже будет иметь значение dbt_valid_to = null.
При настройке снэпшотов в измененных и новых записях существует возможность установить значение '9999-12-31' вместо null для столбца dbt_valid_to.
Также стоит упомянуть о стратегиях выявления изменений.
Таких стратегий всего две:
временная метка (
timestamp), которая использует столбецupdated_atдля определения изменения записи;проверка (
сheck), которая сравнивает текущие и предыдущее значения столбцов таблицы, чтобы определить, изменилась ли запись.
Стратегия временной метки (timestamp)
Стратегия временных меток используется, когда исходные записи содержат поле, которое обновляется при каждом изменении (например, столбец last_update). Движок dbt™ использует этот столбец, чтобы определить, изменилась ли запись с момента последнего запуска снэпшота.
Чтобы использовать данную стратегию, необходимо указать столбец в настройках снэпшотов. dbt™ сравнивает предыдущее значение с текущим значением при каждом запуске. Если временная метка изменилась, dbt™ рассматривает запись как обновленную, завершает предыдущую версию и вставляет новую запись.
Эта стратегия эффективна, однако требует наличия надежного и постоянно обновляемого столбца временных меток в исходных данных. Если временная метка не изменяется при изменении данных, то dbt™ не выполнит обновление снэпшота.
Стратегия проверки (сheck)
Стратегия проверки применяется в случаях, когда в исходной таблице отсутствует столбец с датой/временем обновления. Эта стратегия работает путем сравнения одного или нескольких столбцов между их текущими и предыдущими значениями (например, check_cols = ["phone", "email"]). Если значение в записи какого-либо из этих столбцов изменилось, то dbt™ аннулирует старую запись и запишет новую. Если значения столбцов идентичны, dbt™ не будет предпринимать никаких действий.
Данная стратегия может быть более затратной с точки зрения вычислений, особенно для широких таблиц или больших наборов данных. Важно выбирать только те столбцы, которые, как ожидается, могут измениться, чтобы избежать ненужного управления версиями. Поэтому разработчиками dbt™ рекомендовано использование стратегии временных меток, так как при этой стратегии требуется отслеживать только одну колонку (updated_at), а также уменьшается вероятность возникновения ошибок (например, если несвоевременно будет обновлена настройка стратегии при изменении схемы таблицы, когда добавляются/удаляются столбцы, участвующие в формировании «слепков»).
В случае использования стратегии проверки может возникнуть соблазн настроить для отслеживания изменений все столбцы исходной таблицы, указав check_cols = «all». Хотя такая настройка является штатной, но разработчики dbt™ все-таки рекомендуют перечислять конкретные столбцы, которые необходимо проверять, или же рассмотреть возможность использования суррогатного ключа по нескольким столбца. Затем этот ключ указывать в настройках формирования снэпшота.
Процесс построения снэпшотов
Процесс построения снэпшота в dbt™ содержит следующие этапы:
Определение источника.
Настройка и построение модели снэпшота.
Запуск снэпшота.
Определение источника
В качестве источника для снэпшотов можно использовать как таблицы исходной системы, так и модели staging-слоя. На примере одной из staging-моделей проекта отследим изменение контактной информации заказчиков (stg_pg__customers).
Настройка и построение модели «снэпшота»
До версии dbt™ 1.9 существовала возможность конфигурации снэпшотов только через SQL синтаксис. Но начиная с версии 1.9, можно обойтись настройками с помощью YAML. Хотя вариант с SQL также продолжает функционировать.
Перед началом работы со снэпшотами рекомендуется обновить версию (минимум до 1.9)
Создайте в папке snapshots файл customers_snapshot.yml и добавьте в него следующий код:
snapshots: - name: customers_snapshot relation: ref('stg_pg__customers') config: schema: snapshots unique_key: customer_id strategy: timestamp updated_at: updated_at dbt_valid_to_current: "cast('9999-12-31' as date)"
Запуск снэпшота
Снэпшоты не совсем обычные модели. Как было отмечено ранее, в проекте они хранятся не в общей папке models, а в отдельной snapshots. Более того, для них создается отдельная схема, что является своего рода «защитой от дурака» — потенциального удаления этих таблиц. Поэтому снэпшоты создаются отдельной командой dbt snapshot (или же в рамках общей сборки проекта dbt build).
Выполните в командной строке или терминале команду создания снэпшотов:
dbt snapshot
Команда dbt snapshot запускает сразу все имеющиеся снэпшоты. Если требуется запустить какую-то определенную модель, то используйте команду dbt snapshot --select snapshot_name, где snapshot_name — название модели снэпшота.
Например, запуск рассмотренного ранее снэпшота можно было выполнить так:
dbt snapshot --select customers_snapshot
После запуска команды вы сразу увидите лог с информацией об успешности запуска и формировании снэпшотов, или же возникшей ошибке:
Проверьте полученный результат в базе, перейдите в pgAdmin.
Согласно выполненным настройками создалась новая схема snapshots с таблицей customers_snapshot:
1
2
Пример отслеживания изменений
Для примера возьмите произвольную запись и сымитируйте изменение в системе-источнике (таблица public.customer).
select * from public.customer where customer_id = 1;
1
2
3
Предположим, что данный пользователь (Агата Морозова) сменил фамилию и, соответственно, водительское удостоверение. При внесении изменений в исходной системе также обновится значение временной метки.
Выполните следующий запрос для имитации обновления данных в исходной таблице:
update public.customer set last_name='Кристи', driving_licence_number='5716681479', driving_licence_valid_from='2026-01-01', last_update='2026-01-30 09:00:00' where customer_id = 1;
Проверьте еще раз данные выбранного заказчика после обновления, выполните запрос:
select * from public.customer where customer_id = 1;
1
2
3
Так как снэпшот customers_snapshot построен на staging-модели stg_pg__customers сначала потребуется обновить данную модель с учетом изменений в исходной таблице customer.
Запустите построение модели stg_pg__customers:
dbt run --select stg_pg__customers
Посмотрите изменения в базе. Выполните запрос:
select * from staging.stg_pg__customers where customer_id = 1;
1
2
3
Модель staging-слоя в виде представления в базе успешно обновилась. Вернитесь в VS Code или командную строку и повторите команду создания снэпшотов:
dbt snapshot
Лог указывает на успешное выполнение задания, поэтому можно смело проверять изменения в базе. Вернитесь pgAdmin и выполните запрос:
В выборку для наглядности добавлены поля, значения которых изменились. Но вы можете вывести все поля таблицы.
select customer_id , last_name , driving_licence_number , driving_licence_valid_from , updated_at , dbt_valid_from , dbt_valid_to from snapshots.customers_snapshot where customer_id = 1;
1
2
3
Как видно, снэпшот содержит две строки по выбранному заказчику — до и после изменения. Актуальной является та, у которой значение dbt_valid_to равно 9999-12-31 00:00:00.
Таким образом, вы познакомились в функциональностью dbt™ по отслеживанию изменений. Сохраните текущее состояние проекта.
Сохранение проекта в GitHub
Вернитесь в VS Code и подготовьте измененные файлы проекта для отправки на сервер:
git add .
Добавьте сообщение для коммита:
git commit -m "snapshots"
Отправьте локальный проект в репозиторий GitHub:
git push
Теперь актуальный код проекта хранится в GitHub-репозитории.