Как настроить dbt проект с нуля
Зачем dbt
dbt превращает SQL-запросы в версионируемые, тестируемые модели данных. Вместо ручного поддержания витрин в БД вы описываете их в SQL-файлах, и dbt строит таблицы в правильном порядке с проверками.
Для аналитика это мощный инструмент, который делает вашу работу воспроизводимой. Вместо «у меня есть дашборд, основанный на запросе, который я не помню, где лежит» — чёткая структура с документацией и тестами.
Установка
dbt бывает двух видов: dbt Core (open-source) и dbt Cloud (платная SaaS-версия). Для старта берите Core.
Установка через pip:
pip install dbt-postgres # для PostgreSQL
# или
pip install dbt-bigquery
pip install dbt-snowflake
pip install dbt-clickhouseКаждый adapter отдельно, в зависимости от вашей БД.
Проверка установки:
dbt --versionСоздание проекта
dbt init my_project
cd my_projectdbt init создаёт скелет проекта. Внутри будут:
dbt_project.yml— главная конфигурация.models/— папка для SQL-моделей.tests/— кастомные тесты.macros/— переиспользуемый SQL.seeds/— CSV-файлы для загрузки.snapshots/— snapshot-модели.
Настройка соединения
dbt хранит credentials в ~/.dbt/profiles.yml. Файл выглядит так:
my_project:
target: dev
outputs:
dev:
type: postgres
host: localhost
user: my_user
password: my_password
port: 5432
dbname: my_db
schema: dev_analytics
threads: 4
prod:
type: postgres
host: prod-db.company.com
user: prod_user
password: "{{ env_var('DBT_PROD_PASSWORD') }}"
port: 5432
dbname: prod_db
schema: analytics
threads: 8Несколько окружений (dev, prod) позволяют тестировать локально перед production deployment.
Пароль лучше через env var, чтобы не коммитить в git.
Первая модель
Модели — SQL-файлы в models/. Например, models/staging/stg_orders.sql:
{{ config(materialized='view') }}
SELECT
id AS order_id,
user_id,
amount,
status,
created_at
FROM {{ source('raw', 'orders') }}
WHERE status IS NOT NULL{{ config(materialized='view') }} — говорит dbt сделать это view (виртуальная таблица). Альтернатива — 'table' для физической таблицы.
{{ source('raw', 'orders') }} — ссылка на исходную таблицу. Она должна быть описана в sources.yml:
version: 2
sources:
- name: raw
schema: raw_data
tables:
- name: orders
description: "Сырые заказы из production"Попробовать силы на подобных вопросах проще всего в тренажёре Карьерник — прямо в Telegram, без регистрации через сайт.
Запуск модели
dbt runЭта команда компилирует SQL-модели, строит DAG зависимостей и выполняет их в правильном порядке.
После запуска в вашей БД появится view dev_analytics.stg_orders (по target dev).
Чтобы запустить конкретную модель:
dbt run --select stg_ordersЧтобы запустить модель и всё, что от неё зависит:
dbt run --select stg_orders+Цепочка моделей
Реальные проекты имеют несколько слоёв. Стандартная структура:
models/
├── staging/ # очистка сырых данных
│ ├── stg_orders.sql
│ └── stg_users.sql
├── intermediate/ # промежуточные расчёты
│ └── int_user_orders.sql
└── marts/ # финальные витрины
├── mart_user_metrics.sql
└── mart_daily_revenue.sqlКаждая модель ссылается на предыдущие через ref():
-- models/marts/mart_daily_revenue.sql
{{ config(materialized='TABLE') }}
SELECT
DATE_TRUNC('day', created_at)::DATE AS day,
SUM(amount) AS revenue
FROM {{ ref('stg_orders') }}
WHERE status = 'paid'
GROUP BY 1
ORDER BY 1{{ ref('stg_orders') }} — dbt заменит это на актуальное имя таблицы в нужной схеме.
Тесты
В models/schema.yml описываем ожидания от данных:
version: 2
models:
- name: stg_orders
description: "Очищенные заказы"
columns:
- name: order_id
description: "Уникальный ID заказа"
tests:
- unique
- not_null
- name: user_id
tests:
- not_null
- name: status
tests:
- accepted_values:
values: ['paid', 'refunded', 'pending', 'cancelled']Запускаем тесты:
dbt testЕсли есть ошибки (неуникальный order_id, NULL где быть не должно, неожиданный status), dbt сообщает. Это защита от data quality issues.
Документация
dbt docs generate
dbt docs servegenerate собирает metadata из схемы и моделей. serve запускает локальный веб-сервер с интерактивной документацией. Видно dependencies, описания, тесты.
Для команды — это self-service каталог. Аналитики сами находят нужные таблицы без pingов DE.
Incremental models
Для больших таблиц полная перезапись медленная. Используйте incremental:
{{ config(
materialized='incremental',
unique_key='order_id'
) }}
SELECT * FROM {{ source('raw', 'orders') }}
{% if is_incremental() %}
WHERE created_at > (SELECT MAX(created_at) FROM {{ this }})
{% endif %}При первом запуске dbt делает полную загрузку. Далее — только новые строки.
Пройти 30–50 задач по теме за вечер можно в Telegram-тренажёре. Это то, что отличает «знаю» от «уверенно отвечу на собесе».
Макросы
Переиспользуемый SQL — в макросах:
-- macros/calculate_retention.sql
{% macro calculate_retention_d7(TABLE) %}
SELECT
user_id,
MIN(event_time) AS signup_time,
BOOL_OR(event_time >= MIN(event_time) + INTERVAL '7 day'
AND event_time < MIN(event_time) + INTERVAL '8 day') AS retained_d7
FROM {{ TABLE }}
GROUP BY user_id
{% endmacro %}Использование:
{{ calculate_retention_d7(ref('stg_events')) }}DRY-принцип: не дублировать одну логику в разных моделях.
CI/CD
Для команды — обязательно. При PR в git:
dbt parse— проверка синтаксиса.dbt compile— компиляция без выполнения.dbt run --models state:modified— только изменённые модели.dbt test— все тесты.
Настраивается через GitHub Actions или Jenkins. Без CI/CD большие проекты быстро ломаются.
Типовые ошибки новичка
Использовать SELECT * в staging. Плохо — новые колонки ломают downstream. Лучше явно перечислять.
Сложные модели в staging-слое. Staging только для чистки, вся логика — в intermediate и marts.
Игнорировать тесты. «Потом добавлю» почти всегда означает «никогда». Пишите сразу.
Hardcode schema names. Используйте {{ ref() }} и {{ source() }}, dbt сам подставит правильные.
Один большой commit с десятками моделей. Маленькие PR, понятные reviews, быстрее feedback.
Читайте также
FAQ
dbt Core или dbt Cloud?
Core — бесплатный, гибкий. Cloud — платный с UI и CI/CD. Для команды 10+ — Cloud удобнее.
Сколько времени на освоение?
Базовые команды и модели — за день. Уверенное владение — 2-3 недели.
dbt заменяет Airflow?
Нет. dbt — transformation-инструмент. Airflow — orchestration. Часто используются вместе.
Где хранить CSV для seed?
В папке seeds/ проекта. Через dbt seed они загружаются в БД.