dbt: снэпшоты и метрики

dbt: снэпшоты и метрики

Владимир Трифонов

Домашка

Давайте посмотрим наше домашнее задание. Оно было простое. Файл с источниками:

models/imdb/sources.yml

Файлы с моделями:

models/imdb/imdb_title_ratings.sql
models/imdb/imdb_title_basics.sql
models/imdb/imdb_2022_ratings.sql

И напоследок файл с тестовыми идентификаторами:

seeds/imdb_test_ids.csv

Снэпшоты

Снэпшоты — это специальный инструмент в dbt, который позволяют делать снимок данных на текущий момент времени и сохранять его. Это может быть полезно для работы с данными, которые меняются со временем. Например, у вас может быть таблица с заказами в которой последовательно меняются статусы заказов: новый, укомплектован, отгружен и т.д. И при этом нет таблицы, хранящей историю изменений. А на вопрос, когда можно будет сделать — команда разработки отвечает: “в следующем квартале. Может быть”. Но теперь вы можете это сделать за вечер.

Обычно такие таблицы бывают в реляционный базах данных типа Postgres или Mysql. В базы данных типа BigQuery или Clickhouse данные зачастую стримятся из таких таблиц уже в виде снэпшотов. 

Мы с вами сегодня сделаем снэпшот на немного искусственном примере: сделаем таблицу со статусами наших демо-такси, а потом вручную обновим их и сделаем снэпшот. Приступим. 

Для начала создадим нашу таблицу с текущими статусами такси:

Добавим определение нового источника:

models/chicago_taxi_trips/sources.yml

Теперь давайте определим снэпшот. По сути это будет обычная модель в папке snaphots, но со специальными обертками:

snapshots/taxi_statuses.sql

В target_schema мы указали датасет, где будут хранитmся снэпошоты. Unique_key — идентификатор поля, по которому мы определяем наши сущности. Это может быть номер заказа или номер такси, как в нашем примере. strategy — то, как мы определяем изменение. В данном случае изменением мы считаем изменение поля updated_at.

Запустим команду dbt snapshot:

В результате видим, что dbt создал таблицу MH_Snapshots.taxi_status_snapshot с тремя записями:

Тут нас в первую очередь интересуют столбы dbt_valid_from и dbt_valid_to. Они указывают на то, когда запись перешла в состояние и когда это состояние закончилось. Т.к. Мы сейчас сделали первый снэпшот и таблица еще не менялась, то dbt_valid_to равно null. Если еще раз запустить dbt snapshot, то таблица не изменится:

Давайте теперь изменим одну запись:

Запустим dbt snapshot и посмотрим, что вышло:

Мы видим, что dbt изменил две строки в таблице:

Обновил первую строку, указав время, до которого значение строки было актуально. И добавил еще одну строку с новыми данными, установив там только dbt_valid_from. В нашем примере мы используем только один столбец, но если бы их было несколько, то dbt копировал бы всю строку целиком, у которой изменилось время updated_at.

После этого снэпшот можно использовать, как обычную модель, обращаясь через ref(‘taxi_statuses’). Снэпшоты лучше всего делать первыми моделями, использующими источник, чтобы сохранить изменения как можно большего количества данных. И уже после этого обрабатывать их в моделях для нужд конвеера.

Т.к. Данные в моделях обычно изменяются в течение дня, а конвееры обычно считаются раз в день, то имеет смысл запускать создание снэпшотов чаще, например раз в час. К счастью, для их создания есть отдельная команда dbt snapshot, которую вы можете запускать по cron или в dbt-cloud.

Метрики

Метрики позволяют рассчитывать агрегированные данные по заданным периодам и, при необходимости, в различных срезах. Пробежимся по ним в двух словах. Давайте сделаем метрику, определяющую количество поездок какого-то такси. Подключать метрики можно только к моделям. Давайте сделаем файл metrics.yml:

models/chicago_taxi_trips/metrics.yml

Тут мы задаем название метрики name, описание метрики в поле label, модель, на основе которой мы строим метрику. Затем мы выбираем тип агрегации метрики. Все виды вы можете посмотреть в документации по dbt. В нашем случае мы считаем уникальные значения. Затем идет sql код, который подставляется в агрегацию. timestamp определяет столбец, содержащий время, по которому мы строим метрику. А time_grains — то, по каким временным срезам мы будет строить метрику. Последним в нашем примере идет параметр dimensions. В нем мы указываем срезы, по которым мы будем считать метрику. В данном случае используем идентификатор такси.

Для того, чтобы обращаться к метрикам нам нужно подключить пакет dbt-labs/metrics. Для этого добавьте его в файл packages.yml (если его нет, то создайте его):

packages.yml

И запустите команду dbt deps:

Затем посчитайте модель dbt_metrics_default_calendar:

Она создаст простой календарь со всеми днями с 2010-01-01 по 2029-12-31 включительно:

После этого вы можете создать запрос к метрике. Давайте создадим модель taxi_trips_count.sql:

models/chicago_taxi_trips/taxi_trips_count.sql

И рассчитаем ее:

И посмотрим, что получилось:

Мы видим количество поездок по дням. Давайте изменим код модели и посчитаем количество поездок по неделям в разрезе машин:

И результат:

С помощью метрик у вас появляется единый источник данных для какой-то метрики по заданным срезам и вам не нужно больше каждый раз писать один и тот же код для разных вариантов. Dbt сделает это за вас, исключая ошибки. Ради интереса вы можете посмотреть файл target/compiled/mh_project/models/chicago_taxi_trips/taxi_trips_count.sql.

Также вы можете делать метрики, построенные на других метриках. Например вы можете посчитать метрику количества сессий и расходов, а затем — CPC. Для этого нужно указать в качестве типа метрики derived, а в calculation — формулу, использующую другие метрики. Подробнее об этом — в документации.

Домашнее задание

В качестве домашнего задания сделайте снэпшот для таблицы с рейтингами фильмов. В качестве даты снэпшота — возьмите дату его создания.

Для метрик возьмите в качестве источника данные о продаже ликеров из таблицы bigquery-public-data.iowa_liquor_sales.sales и сделайте метрику, считающую продажи по дням, неделям и месяцам в разрезе городов и описаний товара item_description. Исключите город DAVENPORT из расчета метрики. Постройте таблицу с продажами товаров по месяцам.





Report Page