Хранилища, адаптеры, хуки и операции

Один проект dbt работает на разных хранилищах — и умеет выполнять служебный SQL вокруг моделей.

Адаптер — плагин, переводящий dbt в диалект конкретного хранилища. Хуки и операции — способы выполнить произвольный SQL вокруг моделей или вручную.

Хранилища и адаптеры

Большая часть проекта dbt — стандартный SQL, поэтому переносимость высокая. Различия диалектов берёт на себя адаптер. Один и тот же проект с минимальными правками работает на разных хранилищах:

ХранилищеАдаптерОсобенность
Snowflakedbt-snowflakeЭластичные warehouse'ы, частый выбор для dbt
BigQuerydbt-bigqueryОплата за объём сканирования, партиции
Redshiftdbt-redshiftДистрибуция и сортировка ключей
Postgresdbt-postgresУниверсален, удобен для обучения и малых данных
ClickHousedbt-clickhouseКолоночный, движки таблиц, своя специфика

На сайте есть отдельные курсы по PostgreSQL и ClickHouse — там разобраны диалекты, на которые ложится dbt.

Хуки: SQL вокруг модели

Иногда нужно выполнить SQL до или после построения модели: выдать права на таблицу, собрать статистику, записать аудит-лог. Для этого есть pre-hook и post-hook:

{{ config(
    materialized='table',
    post_hook="grant select on {{ this }} to role analyst"
) }}
select ... from {{ ref('stg_orders') }}

Здесь после каждого построения модели dbt автоматически выдаёт права на чтение роли analyst. Хуки можно задавать и глобально в dbt_project.yml.

Операции: разовый SQL вне моделей

Когда нужно выполнить служебный макрос вручную (создать схему, почистить временные таблицы), используют run-operation:

-- macros/grant_all.sql
{% macro grant_all(role) %}
  {% set sql %}
    grant usage on schema analytics to role {{ role }}
  {% endset %}
  {% do run_query(sql) %}
{% endmacro %}
# Выполнить макрос как разовую операцию
dbt run-operation grant_all --args '{role: analyst}'

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

Адаптер реализует набор «макросов диалекта»: как создать таблицу, как сделать merge, как назвать тип. Когда dbt компилирует модель, он подставляет реализацию из активного адаптера — поэтому {{ config(materialized='table') }} на Postgres и на Snowflake даёт корректный, но разный DDL. Хуки — это просто дополнительный SQL, который адаптер выполняет до/после основного запроса модели в той же транзакции (где хранилище это поддерживает). Операции выполняются вне контекста моделей через run_query.

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

  • Использовать диалект-специфику без оглядки на адаптер. ClickHouse-движки или BigQuery-партиции не перенесутся на Postgres «как есть».
  • Класть бизнес-логику в хуки. Хуки — для служебного SQL (гранты, аудит), а не для трансформаций.
  • Путать хук и операцию. Хук привязан к модели и срабатывает при её сборке; операция запускается вручную через run-operation.

Итоги

  • Адаптер переводит dbt в диалект хранилища (Snowflake, BigQuery, Redshift, Postgres, ClickHouse) — проект переносим.
  • Хуки (pre/post) выполняют служебный SQL до/после модели; не для бизнес-логики.
  • Операции (run-operation) запускают служебные макросы вручную, вне сборки моделей.
Проверьте себя
1. Что делает адаптер dbt (например dbt-snowflake)?
AЗагружает данные из источников
BПереводит dbt в диалект конкретного хранилища (нужный DDL, merge, типы)
CХранит документацию
DЗаменяет SQL
2. Для чего предназначены post-hook?
AДля бизнес-логики трансформаций
BДля служебного SQL после построения модели (например выдать права)
CДля удаления модели
DДля запуска тестов
3. Чем операция (run-operation) отличается от хука?
AНичем
BОперация запускается вручную вне сборки моделей, хук привязан к модели и срабатывает при её построении
CОперация быстрее
DХук нельзя задать в конфиге