Learning Platform
Глоссарий Troubleshooting
Урок 14.03 · 25 мин
Продвинутый
Semantic LayerYAML v2dbt 1.12migration

Semantic Layer v2 YAML: миграция с v1 (dbt 1.12)

В dbt 1.12 (релиз апрель 2026) Semantic Layer получил v2 YAML spec — significant изменение в том, как описываются semantic_models. Это не просто синтаксическая косметика — это architectural shift в том, как dbt видит отношения между data model (физическая таблица) и semantic model (метрика-layer).

В этом уроке мы детально разберём:

  1. Что не нравилось в v1 YAML spec.
  2. Как выглядит v2 spec и в чём improvement.
  3. Migration path: автоматический (dbt-autofix) и manual.
  4. Обратная совместимость и timeline.
  5. Тонкости новых features в v2.

Metric types: simple, ratio, cumulative (dbt II)

Проблемы v1 spec

V1 spec появился в dbt 1.6 (2024). Через 1.5 года использования community обнаружил несколько проблем:

V1 YAML pain points

dbt Labs наблюдал эти проблемы через community feedback и в 1.12 представил v2 spec.


V2 spec: подход «nested under models»

В v2 — semantic_model описывается прямо внутри model definition:

# models/_models.yml (v2)
version: 2
models:
  - name: fct_orders
    description: "Fact table for order analytics"
    columns:
      - name: order_id
        description: "Unique order identifier"
        tests:
          - not_null
          - unique
      - name: customer_id
        description: "FK to customer"
      - name: amount
        description: "Order total amount"
      - name: order_date
        description: "When order was placed"

    # Semantic model nested directly под model
    semantic_model:
      defaults:
        agg_time_dimension: order_date
      entities:
        - name: order_id
          type: primary
        - name: customer_id
          type: foreign
      dimensions:
        - name: order_date
          type: time
          type_params:
            time_granularity: day
        - name: status
          type: categorical
      measures:
        - name: order_amount
          agg: sum
          expr: amount

Сравнение с v1:

# v1 (old)
# models/_models.yml
version: 2
models:
  - name: fct_orders
    description: "..."
    columns: [...]

# semantic_models/_semantic.yml (отдельный файл)
semantic_models:
  - name: orders
    description: "..."   # дубликат!
    model: ref('fct_orders')   # explicit link
    entities: [...]
    dimensions: [...]
    measures: [...]

Что изменилось:

  1. Один файл. model + semantic_model в одном yaml.
  2. Single source of truth для description. Один раз указан, semantic_model его inherit.
  3. No explicit model: ref(...). Это implicit (semantic_model parent model fct_orders).
  4. No semantic_model name. Используется model name (fct_orders).
  5. Tests на columns остаются в model, не дублируются в semantic_model.
NOTE

Backward compatibility: dbt 1.12+ поддерживает оба spec. V1 YAML файлы продолжают работать. V2 YAML — preferred для new development. Через 2-3 versions (dbt 1.14-1.16) v1 может быть deprecated, но это long-term plan.


Полный пример: v1 -> v2 transformation

Реальный пример из проекта.

V1 (старый формат)

models/_orders.yml:

version: 2
models:
  - name: fct_orders
    description: "Fact orders for analytics"
    columns:
      - name: order_id
        description: "Order PK"
        tests:
          - not_null
          - unique
      - name: customer_id
        description: "FK customers"
      - name: product_id
        description: "FK products"
      - name: amount
        description: "Order amount"
      - name: order_date
        description: "Date of order"
      - name: status
        description: "Order status: pending/completed/refunded"

semantic_models/_sm_orders.yml (отдельный файл!):

semantic_models:
  - name: orders
    description: "Fact orders for analytics"   # дубликат описания
    model: ref('fct_orders')
    defaults:
      agg_time_dimension: order_date
    entities:
      - name: order_id
        type: primary
      - name: customer_id
        type: foreign
      - name: product_id
        type: foreign
    dimensions:
      - name: order_date
        type: time
        type_params:
          time_granularity: day
      - name: status
        type: categorical
    measures:
      - name: order_amount
        agg: sum
        expr: amount
      - name: order_count
        agg: count
        expr: order_id

V2 (новый формат)

models/_orders.yml (один файл):

version: 2
models:
  - name: fct_orders
    description: "Fact orders for analytics"
    columns:
      - name: order_id
        description: "Order PK"
        tests:
          - not_null
          - unique
      - name: customer_id
        description: "FK customers"
      - name: product_id
        description: "FK products"
      - name: amount
        description: "Order amount"
      - name: order_date
        description: "Date of order"
      - name: status
        description: "Order status: pending/completed/refunded"

    semantic_model:
      defaults:
        agg_time_dimension: order_date
      entities:
        - name: order_id
          type: primary
        - name: customer_id
          type: foreign
        - name: product_id
          type: foreign
      dimensions:
        - name: order_date
          type: time
          type_params:
            time_granularity: day
        - name: status
          type: categorical
      measures:
        - name: order_amount
          agg: sum
          expr: amount
        - name: order_count
          agg: count
          expr: order_id

semantic_models/_sm_orders.yml — удалить.

Что улучшилось:

  • Один файл вместо двух.
  • Description указан один раз.
  • Tests и semantic в одном месте.
  • При renaming model fct_orders — переименовываем один файл, semantic_model автоматически связан.

V2-only новые features

V2 добавил несколько features, которые сложно/невозможно сделать в v1:

Feature 1: Inherit column descriptions

semantic_model:
  dimensions:
    - name: order_date
      # Описание берётся из model.columns[].description
      # Не нужно дублировать.
      type: time
      type_params:
        time_granularity: day

V1 требовал явный description в semantic_model.dimension. V2 inherits.

Feature 2: Reference column tests

models:
  - name: fct_orders
    columns:
      - name: order_id
        tests:
          - not_null
          - unique

    semantic_model:
      entities:
        - name: order_id
          type: primary
          # Implicitly inherits not_null + unique tests
          # MetricFlow знает, что order_id unique -> может optimize joins

V1 requires manual entity-level constraint declarations. V2 inherits.

Feature 3: Embedded saved queries

semantic_model:
  saved_queries:
    - name: daily_revenue
      query_params:
        metrics: [revenue]
        group_by: [order_date]

V1 saved_queries — отдельный yaml block. V2 — может быть nested.

Feature 4: Materialized measure spans

semantic_model:
  measures:
    - name: revenue
      agg: sum
      expr: amount
      # Новое в v2:
      materialized_span:
        granularity: month   # MetricFlow precomputes monthly aggregates
        retention_days: 365

Это experimental в 1.12, planned для GA в 1.13. Позволяет automated rollup creation.


Migration path

dbt 1.12 поддерживает оба spec. Стратегия миграции:

Option 1: Manual (для маленьких проектов)

# Для каждого semantic_models файла:
1. Открыть models/_models.yml соответствующая dbt model
2. Открыть semantic_models/_sm.yml
3. Скопировать semantic_models[0] (без name, без model, без description)
4. Paste как semantic_model: nested под models[].
5. Удалить semantic_models/_sm.yml
6. Test: dbt parse, mf validate, mf query

Время: ~5 минут на semantic_model. На проекте 20 semantic_models = 100 минут.

Option 2: Automatic через dbt-autofix

# autofix умеет конвертировать
pip install --upgrade dbt-autofix

# Dry-run сначала
dbt-autofix --target-spec=v2-semantic --dry-run .

# Apply
dbt-autofix --target-spec=v2-semantic .

Autofix:

  1. Reads semantic_models/*.yml.
  2. Matches каждый semantic_model с corresponding dbt model.
  3. Merges contents.
  4. Updates models/_models.yml.
  5. Deletes semantic_models/*.yml (optional flag).

Время: автоматическое, 2-3 минуты на проект.

Option 3: Phased mixed (large project)

Если проект большой, делать all-at-once может быть risky. Phased:

Phase 1 (Week 1): Pilot 5 semantic_models. Convert. Test thoroughly.
Phase 2 (Week 2-3): Domain by domain (orders -> customers -> ...).
Phase 3 (Week 4): Verify nothing missed. Delete semantic_models/ directory.

V1 и v2 coexist во время transition — dbt parse обрабатывает оба.


Тонкости миграции

Issue 1: Naming difference

В v1: semantic_model имеет своё name (часто sm_orders или orders).

В v2: name = model name (fct_orders).

Если у вас были metrics, ссылающиеся на v1 names:

# v1
metrics:
  - name: revenue
    type: simple
    type_params:
      measure: order_amount
      semantic_model: orders   # v1 name

После миграции:

# v2 — semantic_model имя теперь fct_orders
metrics:
  - name: revenue
    type: simple
    type_params:
      measure: order_amount
      semantic_model: fct_orders   # renamed

Все references в metrics, saved_queries — нужно обновить. Autofix это делает.

Issue 2: Cross-references

Если semantic_model A reference semantic_model B (через entities), v2 не меняет — entities остаются те же. Только wrapper YAML структура другая.

Issue 3: Time spine

Time spine model description тоже идёт в v2 формате:

# v2
models:
  - name: time_spine_daily
    description: "Daily time spine"
    semantic_model:
      defaults:
        agg_time_dimension: date_day
      time_spine:
        standard_granularity_column: date_day
      dimensions:
        - name: date_day
          type: time
          type_params:
            time_granularity: day

V1 had similar, но в semantic_models: block отдельно.

Issue 4: Documentation

dbt docs generate показывает v2 spec correctly. Но если у вас custom docs site (built on top of manifest.json), нужно проверить, что parser обрабатывает nested semantic_model.


Compatibility timeline

dbt 1.6 (mid 2024):  v1 spec introduced.
dbt 1.10 (2025):     v1 spec stable. Adoption growing.
dbt 1.11 (Q4 2025):  v2 spec preview (experimental).
dbt 1.12 (Apr 2026): v2 spec stable. Recommended for new projects.
dbt 1.13 (planning): v2 default. v1 still works (deprecation warning).
dbt 1.14+:           v1 deprecated. Migration recommended.
dbt 1.16 (future):   v1 removed. v2 only.

Timeline gives 2-3 years для migration. No need to rush. Но новые проекты — сразу v2.


Проверка знанийKnowledge check
Команда выкатила миграцию v1 -> v2 через dbt-autofix. После apply все пытались `mf query` и получают ошибку 'semantic_model not found: orders'. Что произошло и как fix?
ОтветAnswer
Эта ошибка — типичный artifact миграции v1 -> v2. Понимание — необходимо для anyone, кто делает migration. **Что произошло:** В v1 spec semantic_model имеет свой **name**: ```yaml semantic_models: - name: orders ← это имя semantic_model в v1 model: ref('fct_orders') ``` Это **name** используется при cross-references — в metrics, saved_queries, mf queries. В v2 spec semantic_model **inherits name from parent model**: ```yaml models: - name: fct_orders ← это becomes semantic_model name тоже semantic_model: # name: orders ← такого больше нет entities: [...] ``` После миграции semantic_model name изменился с `orders` на `fct_orders`. Все references на `orders` теперь broken. **Где могут быть broken references:** 1. **Metrics:** ```yaml metrics: - name: revenue type: simple type_params: measure: order_amount semantic_model: orders ← broken! Должен быть fct_orders ``` 2. **Saved queries:** ```yaml saved_queries: - name: monthly_revenue query_params: metrics: [revenue] group_by: - orders__order_date ← broken! Должен быть fct_orders__order_date ``` 3. **mf query commands:** ```bash mf query --metrics revenue --group_by orders__country # ← broken! Должен быть fct_orders__country ``` 4. **Documentation references:** Документация может ссылаться на старые names. Не runtime error, но confusing. 5. **External SL consumers:** Если BI tools или Python scripts hardcoded "orders" — они broken. **Solution:** **Step 1: Diagnose breaking references.** ```bash # Search для old name grep -r "semantic_model: orders" . grep -r "orders__" . grep -r "'orders'" . ``` Это покажет все места, где `orders` referenced как semantic_model name. **Step 2: Update references.** Manual replace: ```yaml # Before semantic_model: orders # After semantic_model: fct_orders # Before group_by: [orders__order_date] # After group_by: [fct_orders__order_date] ``` Via sed (osторожно): ```bash find . -name "*.yml" -exec sed -i 's/semantic_model: orders/semantic_model: fct_orders/g' {} \; find . -name "*.yml" -exec sed -i 's/orders__/fct_orders__/g' {} \; ``` Warning: sed может break unrelated мatches (e.g., `orders__product` где orders — продукт name, не semantic_model). Manual review safer. **Step 3: Update consumer code.** If BI tools, Python scripts, или external dashboards ссылаются на old name — update: ```python # Before result = sl_client.query(metrics=['revenue'], group_by=['orders__country']) # After result = sl_client.query(metrics=['revenue'], group_by=['fct_orders__country']) ``` **Step 4: Test thoroughly.** ```bash dbt parse mf validate mf query --metrics revenue --group_by fct_orders__country ``` Если все работает — migration completed. **Step 5: Alias support (workaround).** Если есть legacy external systems которые нельзя обновить, dbt 1.12 поддерживает **semantic_model aliases**: ```yaml models: - name: fct_orders semantic_model: aliases: ["orders", "orders_v1"] ← legacy names accepted entities: [...] ``` Queries с `semantic_model: orders` будут resolved как `fct_orders`. Это **backward compatibility hack**. **Step 6: Plan deprecation alias.** Aliases — temporary. Не permanent solution. Plan: - Месяц 1: Update internal references (metrics, saved_queries, internal scripts). - Месяц 2: Coordinate с BI team to update dashboards. - Месяц 3: Remove aliases. Migration completed. **Prevention:** Если planning v1 -> v2 migration, **upfront**: 1. Audit все references на semantic_model names (grep). 2. List необходимых updates. 3. Either: - Update references **в parallel** к autofix (one commit). - Или **rename semantic_model в model** to preserve name (e.g., model назывался `fct_orders`, после v2 — но semantic_model было `orders` — переименовать model в `orders` или semantic_model в `fct_orders` according). 4. Communicate с consumers (BI team, data scientists) up front. **Главный урок:** Migration v1 -> v2 — это не только syntactic change. **Naming convention изменяется** (semantic_model = model name in v2). Plan ahead, audit references, communicate consumers, use aliases для transition. Иначе — production breakage.

Проверка знанийKnowledge check
Junior спрашивает: 'если v2 такой улучшение, почему dbt Labs не deprecated v1 в 1.12 сразу? Зачем поддерживать оба spec?'
ОтветAnswer
Хороший strategic вопрос. Понимание deprecation strategy — важно для evaluating dbt ecosystem. **Почему dbt Labs поддерживает оба spec long-term:** **1. Existing investments значительны.** К моменту 1.12 (April 2026) v1 spec был в production у тысяч проектов. Forced migration — break massive number of пользователей одновременно. dbt Labs business model критически зависит от trust пользователей. **2. Migration cost для users.** Для большого проекта (100+ semantic_models) migration: - Audit references (часы работы). - Run autofix (минуты). - Manual cleanup (часы). - Testing (дни-неделю). - Coordinate с BI consumers (недели). - Production rollout (carefully). Total: **недели работы senior engineering**. Forced timeline = disrupted projects, lost trust. **3. Software engineering best practice.** **Deprecate gradually**, не **break immediately**. Standard pattern: - Версия N: Introduce v2, support both. - Версия N+1: v2 default, v1 deprecation warning. - Версия N+2-3: v1 deprecated, refuse to parse без --legacy flag. - Версия N+4-5: v1 removed. Для dbt: 1.12 (v2 introduced) -> 1.13-1.14 (warnings) -> 1.16+ (removal). Это **5+ minor versions = 2-3 years**. **4. Ecosystem dependencies.** Dbt не существует в vacuum. Adapters (dbt-snowflake, dbt-bigquery), tools (Datacoves, dbt Cloud features), MetricFlow itself — все нужно update для v2 support. Если v2-only — все ecosystem нужно одновременно update. Phased deprecation gives ecosystem time. **5. Documentation и learning curve.** Tutorials, blog posts, books, courses ссылаются на v1. Если v1 removed — все ресурсы outdated, learning curve для new users круче. Phased deprecation — community постепенно adapts contents. **6. Adapter и SL API compatibility.** dbt Cloud SL API, MetricFlow, external integrations — все built on top of semantic_manifest.json structure. semantic_manifest.json doesn't change drastically (same fields), но adapters need to handle both v1 input formats и v2 input formats. Time для adapter teams. **Что dbt Labs делает explicitly:** 1. **Backward compatibility guarantees:** "v1 spec будет поддерживаться minimum N versions" — стандартная практика. Точные numbers — в roadmap. 2. **Auto-migration tools:** `dbt-autofix` (мы видели) — автоматически конвертирует v1 -> v2. Reduces migration cost. 3. **Deprecation warnings ведутся:** Лог при `dbt parse` на v1 проектах: ``` WARNING: semantic_models spec v1 is deprecated. Migrate to v2 (nested under models). See: https://docs.getdbt.com/upgrade/v2-semantic ``` Это **non-blocking warnings**. Production не ломается. Но видно, что migration recommended. 4. **Documentation prioritizes v2:** Изменение в docs site: v2 examples первые, v1 — legacy section. Soft pressure toward v2 без forcing. **Когда v1 finally remove?** Dbt Labs не commits на exact date. Indicators: - Adoption metrics (% projects на v2). - Community feedback (если v1 still heavily used). - Маjor maintenance burden (v1 + v2 parsing — engineering cost). Likely scenarios: - 1.13 (mid 2026): v2 default, v1 deprecation warning. - 1.14 (late 2026): v1 requires explicit --legacy flag. - 1.15 (2027): v1 produces parser error, --legacy still works. - 1.16+ (2027-2028): v1 removed entirely. Это **2 года** для migration. Достаточно для most projects. **Strategic implication для senior:** 1. **На новых проектах** — сразу v2. No backward compat needs. 2. **На существующих проектах** — migration в 1.13-1.14 release window. Plan capacity, не rushed. 3. **Monitor deprecation timeline** — каждый dbt release notes показывают current status. 4. **External consumers** (BI tools, data clients) — coordinate в advance. Их migration может быть slower than yours. 5. **Don't double-implement** — once migrated к v2, remove v1 files. Avoid maintaining both definitions. **Главный урок:** **deprecation в production software** — multi-year process. Это **good engineering**, не negligence. Don't expect breaking changes immediately. Plan migration в течение several releases. Use auto-migration tools when available. Coordinate с consumers. Это **standard practice** в mature ecosystems (Python, Linux kernel, Postgres все так делают).

Итого

  1. V2 YAML spec в dbt 1.12 — nested semantic_model: под models[]. Single file для model + semantic.
  2. Improvement над v1: no duplication, single source of truth, easier refactoring, better IDE support.
  3. Migration tools: dbt-autofix автоматически конвертирует. Manual путь для small projects.
  4. Backward compatibility: dbt 1.12+ поддерживает оба spec. v1 deprecated, но не removed.
  5. Tricky migration issues: semantic_model name изменяется (теперь = model name), references в metrics/saved_queries нужно обновить.
  6. V2-only features: inherit descriptions, reference column tests, embedded saved_queries, materialized measure spans (experimental).
  7. Timeline: 1.12 — v2 stable, 1.13-1.14 — v2 default + v1 deprecation, 1.16+ — v1 removed (estimated 2-3 года).
  8. Strategic approach: new projects — v2 сразу; existing — phased migration через autofix + reference updates + consumer coordination.

Следующий урок — dbt Semantic Layer API: JDBC, GraphQL, Python SDK, MCP server для AI agents.

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

Результат: 0 из 0
Концептуальный
Вопрос 1 из 5. Что изменилось в Semantic Layer v2 YAML spec (dbt 1.12)?

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

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

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

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