Слои: staging → intermediate → marts

Как не утонуть в моделях: три слоя с чёткими ролями.

Слои моделирования — общепринятый способ организовать модели dbt: staging (чистка сырья), intermediate (бизнес-логика), marts (готовые витрины).

Зачем слои

Без структуры сотня моделей превращается в спагетти, где витрина напрямую читает три источника и дублирует чистку. Слои наводят порядок: у каждого этажа своя задача, и данные текут снизу вверх — от сырья к витринам.

Staging: один к одному с источником

Модель staging оборачивает ровно один источник и делает только лёгкую чистку: переименование колонок к единому стилю, приведение типов, нормализацию регистра. Никаких джойнов и агрегаций. Префикс stg_.

-- models/staging/stg_orders.sql
select
    id            as order_id,
    customer_id,
    cast(amount as numeric) as amount,
    lower(status) as status,
    created_at
from {{ source('raw', 'orders') }}

Intermediate: бизнес-логика и джойны

Слой intermediate соединяет несколько staging-моделей и применяет бизнес-правила: расчёт признаков, фильтры, промежуточные агрегации. Это «кухня», результат которой ещё не подают пользователю. Префикс int_.

-- models/intermediate/int_orders_with_customer.sql
select
    o.order_id,
    o.amount,
    c.email,
    c.country
from {{ ref('stg_orders') }} as o
join {{ ref('stg_customers') }} as c
  on o.customer_id = c.customer_id

Marts: витрины для бизнеса

Слой marts — конечный продукт: чистые, понятные таблицы, на которые смотрят аналитики и BI. Часто группируются по предметным областям (finance, marketing). Обычно материализуются как table.

-- models/marts/finance/fct_daily_revenue.sql
{{ config(materialized='table') }}
select
    date(created_at) as order_date,
    country,
    sum(amount)      as revenue
from {{ ref('int_orders_with_customer') }}
group by 1, 2

Поток данных

source (сырьё)
   |
   v
stg_*  (чистка 1:1)
   |
   v
int_*  (джойны, бизнес-логика)
   |
   v
mart   (витрина для BI)

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

Слои — это соглашение, а не встроенная сущность dbt: технически все они обычные модели, связанные через ref(). Сила в дисциплине. staging переиспользуется множеством intermediate-моделей, поэтому чистка пишется один раз. Если источник переименует колонку — правка в одной staging-модели, и весь слой выше получает исправление. Это и есть DRY на уровне архитектуры данных.

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

  • Витрина читает source напрямую. Теряется переиспользование чистки — всегда заходите через staging.
  • Джойны в staging. staging — это 1:1 с источником, без соединений.
  • Бизнес-логика в marts. Сложную логику выносят в intermediate, чтобы marts оставались тонкими и читаемыми.

Итоги

  • staging чистит сырьё 1:1, intermediate содержит джойны и бизнес-логику, marts — готовые витрины.
  • Данные текут снизу вверх через ref(); слои — соглашение, дающее DRY и порядок.
  • Чистка пишется один раз в staging и переиспользуется выше.
Проверьте себя
1. Какова роль слоя staging?
AСчитать финальные витрины
BЛёгкая чистка одного источника 1:1: переименование, приведение типов, без джойнов
CХранить документацию
DСоединять десятки таблиц
2. Почему витрина не должна читать source напрямую, минуя staging?
AЭто запрещено синтаксисом dbt
BТеряется переиспользование чистки — её пришлось бы дублировать
CSource работает медленнее
DТак требует SQL-стандарт
3. Слои staging/intermediate/marts в dbt — это…
AВстроенные типы объектов
BСоглашение об организации обычных моделей, связанных через ref()
CТри разные базы данных
DТри разных инструмента