Создание семантических моделей
Как создать семантическую модель
Семантическая модель — это эквивалент логической модели на уровне Semantic Layer (то, что исторически в мире dbt называлось просто «моделью»). Так же как конфигурации для моделей определяются в YAML-ключе models:, конфигурации для семантических моделей размещаются под ключом semantic models:. Ключевое отличие заключается в том, что если логическая модель состоит из конфигурации и SQL- или Python-кода, то семантическая модель определяется исключительно с помощью YAML. Вместо кодирования конкретного набора данных семантическая модель описывает связи и выражения, которые позволяют конечным пользователям динамически и надёжно выбирать и уточнять собственные наборы данных.
- ⚙️ Семантические модели состоят из трех компонентов:
- 🫂 сущности: они описывают отношения между различными семантическими моделями (подумайте об идентификаторах)
- 🔪 измерения: это столбцы, по которым вы хотите разбивать, группировать и фильтровать (подумайте о временных метках, категориях, булевых значениях).
- 📏 меры: это количественные значения, которые вы хотите агрегировать
- 🪣 Мы определяем столбцы как сущность, измерение или меру. Столбцы обычно попадают в одну из этих 3 категорий, или, если это сложное выражение агрегации, они могут составлять метрику.
Определение заказов
Давайте подробнее рассмотрим, как мы можем определить семантическую модель заказов.
- 📗 Мы определяем ее как YAML-словарь в списке
semantic_models. - 📑 Она будет иметь имя, список сущностей, список измерений и список мер.
- ⏬ Мы рекомендуем определять их в этом порядке последовательно как лучшую практику стиля.
semantic_models:
- name: orders
entities: ... # мы определим их позже
dimensions: ... # мы определим их позже
measures: ... # мы определим их позже
Далее мы укажем на соответствующую логическую модель, передав ref в свойстве model:, а также зададим description для документации.
semantic_models:
- name: orders
description: |
Модель, содержащая данные о заказах. Зерно таблицы — идентификатор заказа.
model: ref('stg_orders')
entities: ...
dimensions: ...
measures: ...
Установление наших сущностей
- 🫂 Entities — это объекты и концепции в наших данных, которые имеют измерения и метрики. Их можно представить как существительные нашего проекта, опорные оси запросов, по которым мы хотим агрегировать данные, или просто как ключи для соединений.
- 🔀 Entities помогают MetricFlow понять, как различные semantic models связаны друг с другом.
- ⛓️ В отличие от многих других семантических слоёв, в MetricFlow нам не нужно явно описывать join’ы — вместо этого связи неявно задаются через entities.
- 1️⃣ Каждый semantic model должен иметь одну primary entity, определённую для него самого, и любое количество foreign entities для других semantic models, к которым он может присоединяться.
- 🫂 Entities требуют указания имени и типа
- 🔑 Доступные типы: primary, foreign, unique или natural — сейчас мы сосредоточимся на первых двух, а подробнее про unique и natural можно прочитать здесь.
Сущности в действии
Если мы посмотрим на пример модели подготовки для заказов, мы увидим, что у нее есть 3 столбца идентификаторов, поэтому нам понадобятся три сущности.
renamed as (
select
---------- ids
id as order_id,
store_id as location_id,
customer as customer_id,
---------- properties
(order_total / 100.0) as order_total,
(tax_paid / 100.0) as tax_paid,
---------- timestamps
ordered_at
from source
- 👉 Мы добавляем их с
name,typeи необязательнымexpr(выражение). Выражение может быть любым допустимым SQL-выражением на вашей платформе. - 📛 Если вы не добавите выражение, MetricFlow предположит, что имя равно имени столбца в подлежащей логической модели.
- 👍 Наша лучшая практика — по возможности предоставлять
name, который является единственным числом предмета или зерна таблицы, и использоватьexprдля указания точного имени столбца (с_idи т.д.). Это позволит нам писать более читаемые метрики поверх этих семантических моделей. Например, мы будем использоватьlocationвместоlocation_id.
semantic_models:
- name: orders
...
entities:
# мы используем столбец для имени здесь, потому что order является зарезервированным словом в SQL
- name: order_id
type: primary
- name: location
type: foreign
expr: location_id
- name: customer
type: foreign
expr: customer_id
dimensions:
...
measures:
...
Определение наших измерений
- 🧮 Dimensions (измерения) — это столбцы, по которым мы хотим фильтровать и группировать данные, своего рода «прилагательные» нашего проекта. Они бывают трёх типов:
- categorical
- time
- slowly changing dimensions — они описаны в документации и немного более сложные. Чтобы сосредоточиться на формировании ментальной модели основ MetricFlow, в этом руководстве мы не будем использовать SCD.
- ➕ Мы не ограничены только существующими столбцами — с помощью свойства
exprможно добавлять простые вычисления в измерения. - 📛 Categorical dimensions — самые простые. Для них достаточно указать
nameиtype(гдеtype— categorical). Если значение свойстваnameсовпадает с именем столбца измерения, на этом всё — настройка завершена. Если же вы хотите или вам нужно использоватьname, отличное от имени столбца, либо выполнить фильтрацию или вычисление, вы можете указать необязательное свойствоexpr, которое будет вычисляться для этого измерения.
Измерения в действии
- 👀 Давайте снова посмотрим на нашу модель подготовки и посмотрим, какие поля у нас доступны.
select
---------- ids -> entities
id as order_id,
store_id as location_id,
customer as customer_id,
---------- numerics -> measures
(order_total / 100.0) as order_total,
(tax_paid / 100.0) as tax_paid,
---------- timestamps -> dimensions
ordered_at
from source
- ⏰ На данный момент единственное измерение, которое нужно добавить, это временное измерение:
ordered_at. - 🕰️ По крайней мере одно основное временное измерение требуется для любых семантических моделей, которые имеют меры.
- 1️⃣ Мы обозначаем это с помощью свойства
is_primary, или если предоставлено только одно временное измерение, оно является основным по умолчанию. Ниже у нас есть толькоordered_atкак временная метка, поэтому нам не нужно указывать ничего, кроме минимальной гранулярности, к которой мы группируем (в данном случае, день). Под этим мы подразумеваем, что мы не будем рассматривать заказы с более мелкой гранулярностью, чем день.
dimensions:
- name: ordered_at
expr: date_trunc('day', ordered_at)
type: time
type_params:
time_granularity: day
Модели измерений. У вас могут быть некоторые модели, которые не содержат мер, только измерительные данные, которые обогащают другие факты. Это совершенно нормально, семантическая модель не требует измерений или мер, ей просто нужна основная сущность, и если у вас есть меры, основное временное измерение.
Мы обсудим альтернативную ситуацию, измерительные таблицы, которые имеют статические числовые значения, такие как затраты на поставку или налоговые ставки, но не имеют временных измерений, позже в Руководстве.
- 🔢 Мы также можем создать измерение из числового столбца, который обычно был бы мерой.
- 🪣 Используя
expr, мы можем создавать группы значений, которые мы маркируем для нашего измерения. Мы добавим одну из них для маркировки 'больших заказов' как любых заказов с общей суммой более $50.
dimensions:
- name: ordered_at
expr: date_trunc('day', ordered_at)
type: time
type_params:
time_granularity: day
- name: is_large_order
type: categorical
expr: case when order_total > 50 then true else false end
Создание наших мер
- 📏 Меры — это последний компонент семантической модели. Они описывают числовые значения, которые мы хотим агрегировать.
- 🧱 Меры формируют строительные блоки метрик, с сущностями и измерениями, которые помогают нам правильно комбинировать, группировать и фильтровать эти метрики.
- 🏃 Вы можете думать о них как о глаголах семантической модели.
Меры в действии
- 👀 Давайте посмотрим на нашу модель подготовки в последний раз и посмотрим, какие поля мы хотим измерить.
select
---------- ids -> entities
id as order_id,
store_id as location_id,
customer as customer_id,
---------- numerics -> measures
(order_total / 100.0) as order_total,
(tax_paid / 100.0) as tax_paid,
---------- timestamps -> dimensions
ordered_at
from source
- ➕ Здесь
order_totalиtax paid— это колонки, которые мы хотим использовать в качестве мер. - 📝 Мы можем описать их с помощью кода ниже, указав name, description, aggregation и expression.
- 👍 Как и раньше, MetricFlow по умолчанию будет использовать name, совпадающее с именем колонки, если expression не задано.
- 🧮 Нам доступно множество различных агрегаций. Здесь нам нужны просто суммы.
measures:
- name: order_total
description: Общая сумма для каждого заказа, включая налоги.
agg: sum
- name: tax_paid
description: Общая сумма налога, уплаченного за каждый заказ.
agg: sum
- 🆕 Мы также можем создавать новые меры, используя выражения, например, добавляя количество отдельных заказов, как показано ниже.
- name: order_count
description: Количество отдельных заказов.
expr: 1
agg: sum
Проверка нашей работы
Наш завершенный код будет выглядеть так, наша первая семантическая модель! Вот два примера, показывающие разные подходы к организации:
Как вы можете видеть, содержимое семантической модели идентично в обоих подходах. Ключевые различия:
-
Расположение файла
- Подход с совместным расположением:
models/marts/orders.yml - Подход с параллельной поддиректорией:
models/semantic_models/sem_orders.yml
- Подход с совместным расположением:
-
Именование файла
- Подход с совместным расположением: Использует то же имя, что и соответствующий mart (
orders.yml) - Подход с параллельной поддиректорией: Добавляет префикс
sem_к файлу (sem_orders.yml)
- Подход с совместным расположением: Использует то же имя, что и соответствующий mart (
Выберите подход, который лучше всего соответствует структуре вашего проекта и предпочтениям команды. Подход с совместным размещением (co-located) часто проще для новых проектов, тогда как подход с параллельными подкаталогами может быть более наглядным при миграции крупных существующих проектов в Semantic Layer.
Следующие шаги
Давайте рассмотрим основы семантических моделей:
- 🧱 Состоят из сущностей, измерений и мер.
- 🫂 Описывают семантику и отношения объектов в хранилище.
- 1️⃣ Соответствуют одной логической модели в вашем проекте dbt.
Далее, давайте используем нашу новую семантическую модель для создания метрики!