Макросы и пакет dbt_utils

Когда один и тот же кусок SQL повторяется в десяти моделях — пора писать макрос.

Макрос — именованный, параметризуемый фрагмент Jinja/SQL (аналог функции), который можно вызывать из любой модели для переиспользования логики.

Зачем макросы

DRY (Don't Repeat Yourself) применим и к SQL. Если в пяти моделях вы пишете один и тот же хитрый CASE для конвертации валют или одинаковую очистку телефона, любая правка означает пять одинаковых изменений. Макрос выносит логику в одно место.

Объявление макроса

-- macros/cents_to_dollars.sql
{% macro cents_to_dollars(column_name, decimals=2) %}
  round({{ column_name }} / 100.0, {{ decimals }})
{% endmacro %}

Теперь вызов в любой модели:

select
    order_id,
    {{ cents_to_dollars('amount_cents') }} as amount_usd,
    {{ cents_to_dollars('tax_cents', 4) }} as tax_usd
from {{ ref('stg_orders') }}

На этапе компиляции {{ cents_to_dollars('amount_cents') }} раскроется в round(amount_cents / 100.0, 2). Логика описана один раз, используется везде.

Пакет dbt_utils: готовые макросы

Сообщество собрало частые приёмы в пакет dbt_utils. Не нужно изобретать заново генерацию суррогатного ключа, сводную таблицу дат или проверку «звёздочкой».

select
  {{ dbt_utils.generate_surrogate_key(['order_id', 'line_id']) }} as line_key,
  *
from {{ ref('stg_order_lines') }}
Макрос dbt_utilsЧто делает
generate_surrogate_keyХэш-ключ из нескольких колонок
starSELECT всех колонок, кроме указанных
date_spineСплошной календарь дат
pivotРазворот строк в колонки

Подключение пакета

# packages.yml
packages:
  - package: dbt-labs/dbt_utils
    version: 1.1.1
# Установить пакеты, объявленные в packages.yml
dbt deps

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

Макрос — это та же Jinja-функция, что и встроенные ref()/source(); просто вы пишете её сами. При компиляции dbt подставляет тело макроса с заданными аргументами в место вызова. Пакет — это набор чужих макросов (и иногда моделей), которые dbt deps скачивает в папку dbt_packages/, после чего они доступны через префикс пакета (dbt_utils.).

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

  • Дублировать логику вместо макроса. Повтор одного и того же SQL в моделях — главный сигнал, что нужен макрос.
  • Изобретать то, что есть в dbt_utils. Сперва проверьте, нет ли готового макроса.
  • Забыть dbt deps. Объявить пакет в packages.yml мало — его надо установить.

Итоги

  • Макрос — функция для переиспользования SQL; объявляется в macros/, вызывается из моделей.
  • Пакет dbt_utils даёт готовые макросы (surrogate_key, star, date_spine) — не изобретайте заново.
  • Пакеты объявляют в packages.yml и ставят командой dbt deps.
Проверьте себя
1. Что такое макрос в dbt?
AТип материализации
BИменованный параметризуемый фрагмент SQL/Jinja (аналог функции) для переиспользования
CКоманда запуска
DФайл подключения
2. Что нужно сделать после добавления пакета в packages.yml?
AПерезапустить хранилище
BВыполнить dbt deps, чтобы скачать пакет
CНичего, он подключится сам
DНаписать макрос вручную