Learning Platform
Глоссарий Troubleshooting
Урок 15.02 · 20 мин
Начальный
NamingConventionsPrefixstg_int_fct_dim_

Naming conventions для моделей

В предыдущем уроке мы посмотрели три слоя. Каждый слой имеет свой префикс имени файла. Это не косметика — имена несут информацию о роли модели, и хорошие имена позволяют читать DAG без открытия dbt docs.

В этом уроке — полный набор conventions из community / dbt Labs guide, типичные ошибки и почему именно эти соглашения, а не другие.


Сводная таблица префиксов

СлойПрефиксФормат имениПример
stagingstg_stg_<source>__<table>.sqlstg_jaffle__customers.sql
intermediateint_int_<purpose>.sqlint_order_items_pivoted.sql
marts (fact)fct_ (опционально)fct_<entity>.sql или <entity>.sqlfct_orders.sql, orders.sql
marts (dim)dim_ (опционально)dim_<entity>.sql или <entity>.sqldim_customers.sql, customers.sql

Кроме того есть несколько менее распространённых:

ПрефиксПрименениеПример
base_Чистка до staging (используется в больших проектах)base_jaffle__customers_unioned.sql
agg_Aggregations (в больших mart-проектах)agg_revenue_daily.sql
rpt_Report-таблицы (специально для BI)rpt_executive_dashboard.sql
wide_Wide-таблицы с денормализациейwide_customer_360.sql

В курсе придерживаемся базового набора: stg_, int_, fct_, dim_ или без префикса для marts.


staging: stg_<source>__<table>

Полный формат: stg_<source>__<table>. Двойное подчёркивание между source и table — это важная convention из dbt Labs.

Зачем __ (а не _):

  1. Парсимость. stg_jaffle__customer_orders явно: source = jaffle, table = customer_orders. Одинарное _ создало бы амбивалентность: где кончается source и начинается table?
  2. Уникальность среди источников. Два source могут иметь таблицу customers. У вас получится stg_jaffle__customers и stg_shopify__customers — никаких коллизий.
  3. Эстетика и привычка. Все профессиональные dbt-проекты пишут так. Если придёшь в team — все ожидают этот формат.
Разбор имени stg_jaffle__customer_orders

Антипаттерны:

  • staging_customers.sql — нет префикса stg_, нет source. Через 6 месяцев не помните, откуда оно пришло.
  • stg_customers.sql — без source. Если source один (только jaffle), допустимо в маленьком проекте. В production-проектах с 3+ sources — обязательно с source.
  • stg_jaffle_customers.sql — одинарное подчёркивание, не парсится. Где конец source: jaffle или jaffle_customer?
  • stg_jaffle.customers.sql — точка в имени файла. ОС/git могут путаться.

intermediate: int_<purpose>

int_<purpose>.sql — имя описывает что делает модель, не откуда берётся.

Хорошие примеры:

  • int_order_items_pivoted.sql — order_items в widе-формат.
  • int_payments_joined.sql — JOIN payments на orders.
  • int_active_customers.sql — фильтр активных клиентов.
  • int_revenue_by_segment.sql — pre-aggregation по сегментам.

Плохие примеры:

  • int_orders.sql — слишком общее. Что делает? Pivot? JOIN? Agregate?
  • int_jaffle_customers.sql — не нужен префикс source в intermediate. Intermediate — это наша логика, не привязка к source.
  • int_customers_v2.sql — версионирование в имени файла — антипаттерн (используйте git).

Если imediate-модель относится к домену, можно положить её в поддиректорию:

models/intermediate/
  finance/
    int_payments_joined.sql
    int_revenue_by_segment.sql
  marketing/
    int_campaign_costs_pivoted.sql

В этом случае имя файла не нужно префиксить finance_ — это видно из директории.


marts: с префиксами или без

Здесь сообщество разделено на два лагеря.

Лагерь 1 — Kimball-style с префиксами:

models/marts/
  fct_orders.sql        ← fact-таблица
  fct_payments.sql      ← fact
  dim_customers.sql     ← dimension
  dim_products.sql      ← dimension

Префикс сразу говорит роль таблицы. Удобно для классической data warehousing терминологии.

Лагерь 2 — без префиксов, бизнес-имена:

models/marts/
  orders.sql
  payments.sql
  customers.sql
  products.sql

Логика: «аналитики не различают fact и dim в SQL, для них это просто таблицы». В BI Tableau показывает customers без префикса, дашборд читается естественно.

Оба варианта валидны. Выбирайте один на проект и придерживайтесь. Mixing — антипаттерн (некоторые с fct_, некоторые без).

В курсе используем Kimball-style с префиксами, потому что это сильнее видно в DAG и проще для junior-обучения.


Поддиректории внутри marts

В больших проектах marts тоже разбивают на домены:

models/marts/
  core/
    fct_orders.sql           ← общие fact'ы и dim'ы
    dim_customers.sql
    dim_products.sql
  finance/
    fct_payments.sql
    revenue_daily.sql
  marketing/
    campaign_attribution.sql
    fct_sessions.sql
  ops/
    fulfillment_metrics.sql

core/ — это общие marts, на которые опираются другие домены. finance/, marketing/, ops/ — domain-specific marts.

Это аналог bounded context из Domain-Driven Design.


Имена колонок: snake_case, бизнес-первое

В staging уже переименовали колонки в snake_case. В marts добавляются новые колонки, и для них есть свои conventions:

  • snake_case для всех колонок. total_amount, is_active, created_at.
  • Не сокращения. customer_id, не cust_id. amount, не amt. Исключения для очень распространённых: id, ts.
  • Booleans с is_ / has_ префиксом. is_active, is_deleted, has_orders, has_subscription.
  • Timestamps с _at суффиксом. created_at, updated_at, deleted_at.
  • Dates с _date суффиксом (когда это именно date, не timestamp). order_date, birth_date.
  • Count’ы с префиксом или суффиксом count. order_count или count_orders.
  • Money с unit’ом в имени (для multi-currency проектов). amount_usd, price_eur.

Пример хорошей таблицы dim_customers:

customer_id          -- primary key
first_name
last_name
email
is_email_verified
created_at           -- timestamp когда создан
first_order_date     -- date первого заказа
last_order_date      -- date последнего заказа
order_count          -- count'ов
lifetime_revenue_usd -- USD сумма
is_active            -- boolean
tier                 -- категория (standard / premium / vip)

ID-колонки и primary keys

Соглашение: primary key = <entity>_id, не id.

  • customers.customer_id, не customers.id.
  • orders.order_id, не orders.id.

Зачем: в JOIN’ах вы пишете ON o.customer_id = c.customer_id, а не ON o.customer_id = c.id. Это симметричный JOIN, легко читается, не нужно помнить, какая таблица справа какая слева.

Foreign keys — то же имя, что primary key referenced таблицы:

  • В orders колонка customer_id указывает на customers.customer_id.
  • В order_items колонка order_id указывает на orders.order_id.

Пример полного дерева Jaffle Shop

models/
  staging/
    jaffle/
      _jaffle__sources.yml
      _jaffle__models.yml
      stg_jaffle__customers.sql
      stg_jaffle__orders.sql
      stg_jaffle__order_items.sql
      stg_jaffle__payments.sql
      stg_jaffle__products.sql
  intermediate/
    finance/
      _int_finance__models.yml
      int_order_items_pivoted.sql
      int_payments_joined.sql
    marketing/
      _int_marketing__models.yml
      int_active_customers.sql
  marts/
    core/
      _core__models.yml
      fct_orders.sql
      dim_customers.sql
      dim_products.sql
    finance/
      _finance__models.yml
      fct_payments.sql
      revenue_daily.sql
    marketing/
      _marketing__models.yml
      customer_segmentation.sql
seeds/
  reference/
    country_codes.csv
    product_categories.csv

Глянули на дерево — сразу понимаете архитектуру:

  • jaffle — source с 5 таблицами,
  • финансы и маркетинг — два домена,
  • intermediate-блоки идут по доменам,
  • marts разделены на core (общее) и domain-specific.

Это читаемая структура. В команде новый человек открыл проект — и через 10 минут ориентируется.


Антипаттерны в naming

Антипаттерны naming

Как читается DAG из имён

Хорошие имена позволяют читать DAG без открытия dbt docs. Пример: вы видите модель fct_orders.sql и читаете её код:

SELECT * FROM {{ ref('stg_jaffle__orders') }}
JOIN {{ ref('int_order_items_pivoted') }} ...
JOIN {{ ref('dim_customers') }} ...

Из одних имён понятно:

  • fct_orders — это fact-таблица в marts.
  • Зависит от stg_jaffle__orders — staging для таблицы orders из jaffle source.
  • Зависит от int_order_items_pivoted — intermediate, который делает pivot order_items.
  • Зависит от dim_customers — dimension клиентов из marts.

Никакой документации не нужно: имена самодостаточны. Это вершина naming conventions — когда код читается как proza.


Попробуй сам

Возьмите свой dbt-проект (или Jaffle Shop). Переименуйте файлы согласно conventions.

Чек-лист:

  1. staging: все файлы stg_<source>__<table>? Двойное подчёркивание? snake_case?
  2. intermediate: все файлы int_<purpose>? Поддиректории по доменам?
  3. marts: единый стиль (с fct_/dim_ или без)? Без сокращений?
  4. YAML-файлы: _<group>__<type>.yml (например, _jaffle__sources.yml)? Подчёркивание в начале — чтобы YAML файлы группировались в начале листинга.
  5. Колонки в SQL: snake_case? Bool с is_/has_? Timestamp с _at? Date с _date?

После переименования запустите dbt run. Если что-то ломается — это потому, что были hardcoded ссылки на старые имена в downstream models. Найдите и исправьте.

Бонус: добавьте dbt source freshness и dbt build. Проверьте, что DAG корректно строится по новым именам.


Ключевые выводы

  1. Префиксы по слоям: stg_ (staging), int_ (intermediate), fct_/dim_ или без префикса (marts). Mixing — антипаттерн.
  2. staging имена: stg_<source>__<table> — двойное подчёркивание между source и table. Уникальные через source, парсимые.
  3. intermediate имена: int_<purpose> — описывает действие, не source. Поддиректории по доменам в больших проектах.
  4. marts имена: либо Kimball-style (fct_orders, dim_customers), либо без префикса (orders, customers). Выбирайте один стиль и держитесь.
  5. Колонки: snake_case, не сокращения, is_/has_ для bool, _at для timestamp, _date для date.
  6. Primary key: <entity>_id, не просто id. Foreign key — то же имя в referencing-таблице.
  7. YAML-файлы: _<group>__<type>.yml, начинаются с подчёркивания — чтобы в листинге группироваться сверху.
  8. Хорошие имена позволяют читать DAG без документации — каждое имя сообщает роль и зависимости.
Production naming: миграции и deprecation
Проверка знанийKnowledge check
В проекте две source-системы: основное приложение `app` и CRM `salesforce`. У обеих есть таблица `accounts`. Как назвать staging-модели?
ОтветAnswer
Стандартный паттерн: `stg_<source>__<table>`:\n\n```\nmodels/staging/app/stg_app__accounts.sql\nmodels/staging/salesforce/stg_salesforce__accounts.sql\n```\n\nПрефикс источника обязателен, потому что:\n1. Без него два файла `stg_accounts.sql` создадут **коллизию в DAG** (dbt не позволит два узла с одним именем).\n2. В downstream-моделях `{{ ref('stg_app__accounts') }}` явно — какой источник используется.\n3. В `dbt docs` сразу видно, из какого источника пришла таблица.\n4. Удобно делать intermediate `int_accounts_unioned.sql`, которая JOIN-ит / UNION-ит две staging-таблицы в единое представление.\n\nКак правило, если у вас 2+ источников, **всегда** ставьте source в имя staging-модели, даже если в одном источнике название таблицы уникальное. Будущая консистентность важнее текущей лаконичности.
Проверка знанийKnowledge check
Команда смешала naming в marts: `fct_orders.sql`, `dim_customers.sql`, но также `revenue_daily.sql` (без префикса), `campaign_attribution.sql` (без префикса). Это нормально или проблема?
ОтветAnswer
Это **слабый антипаттерн**. С точки зрения dbt всё работает; с точки зрения читаемости — проблемно.\n\nЧто плохо:\n1. **Несогласованность.** Открыв `marts/`, неясно: `revenue_daily` это fact или агрегатная таблица? Aggregation отдельно (`agg_`) или это часть fact?\n2. **Confusing для новичков.** Новый team-member думает: «`fct_` — это обязательный префикс или нет? Когда добавлять?». Без правила решение принимается случайно.\n3. **Поиск ломается.** `grep "fct_"` найдёт только часть fact'ов.\n\nКак исправить (два варианта):\n\n**Вариант A — все с префиксами:** `fct_orders`, `dim_customers`, `agg_revenue_daily` (или `fct_revenue_daily`, если это fact с granularity 'день'), `fct_campaign_attribution` (или `agg_`).\n\n**Вариант B — все без префиксов:** `orders`, `customers`, `revenue_daily`, `campaign_attribution`. Принимаем business-naming.\n\nЛюбой согласованный стиль > inconsistent. Документируйте выбор в README проекта.

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 5. В проекте 2 source: `app` и `salesforce`. У обоих есть таблица `accounts`. Как правильно назвать staging-модели?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 4