Основные концепции#
Семантический слой состоит из четырех основных компонентов, которые вы настраиваете декларативно в YAML-конфигах, и одного центрального движка, который автоматически генерирует оптимизированный SQL.
Что вы настраиваете:
- Sources — откуда брать данные (SQL-запросы к DWH)
- Enrichments — как обогащать данные дополнительными колонками (LEFT JOIN)
- Metrics — как считать метрики (фильтры, агрегации, отношения)
- Dimensions — какие разрезы доступны для группировки
Что происходит на стороне Trisigma:
- Trisigma Semantic Engine анализирует ваши конфиги и генерирует SQL
- Enrichments применяются только когда нужны
- SQL оптимизирован для эффективного выполнения
- Метрики становятся доступны в отчетах АБ, M42 и (в будущем) в витринах
Ниже показана полная картина того, как компоненты связаны между собой:
graph TB
Source["Source<br/>(исходные данные)"]
Enrichments["Enrichments<br/>(добавленные колонки)"]
EnrichedSource["Enriched Source<br/>(формируется автоматически)"]
Metrics["Metrics"]
Dimensions["Dimensions"]
Engine["Trisigma Semantic Engine<br/>(генерирует SQL)"]
Adhoc["Adhoc Queries"]
Reports["Experiment Reports"]
M42["M42"]
Datamarts["Datamarts/Datasets"]
Source --> Enrichments
Enrichments --> EnrichedSource
EnrichedSource --> Metrics
EnrichedSource --> Dimensions
Metrics --> Engine
Dimensions --> Engine
Engine --> Adhoc
Engine --> Reports
Engine --> M42
Engine --> Datamarts
style Source fill:#e3f2fd,stroke:#333,stroke-width:2px
style Enrichments fill:#e3f2fd,stroke:#333,stroke-width:2px
style EnrichedSource fill:#f5f5f5,stroke:#333,stroke-width:2px
style Metrics fill:#e3f2fd,stroke:#333,stroke-width:2px
style Dimensions fill:#e3f2fd,stroke:#333,stroke-width:2px
style Engine fill:#f5f5f5,stroke:#333,stroke-width:2px
style Adhoc fill:#f5f5f5,stroke:#333,stroke-width:2px
style Reports fill:#f5f5f5,stroke:#333,stroke-width:2px
style M42 fill:#f5f5f5,stroke:#333,stroke-width:2px
style Datamarts fill:#f5f5f5,stroke:#333,stroke-width:2px
Структура репозитория#
Репозиторий ab-metrics имеет следующую структуру папок:
ab-metrics/
├── sources/
│ ├── sql/ # SQL-запросы источников данных
│ │ ├── buyer_stream.sql
│ │ ├── seller_stream.sql
│ │ └── ...
│ └── sources.yaml # Конфигурация источников с метаданными
│
├── enrichments/ # YAML-файлы с enrichments
│ ├── buyer_segment.yaml
│ ├── traffic_source.yaml
│ └── ...
│
├── metrics/ # YAML-файлы с метриками
│ ├── buyer_stream.yaml
│ ├── conversion.yaml
│ └── ...
│
└── dimensions/
├── sql/ # SQL-справочники для dimensions
│ ├── platform.sql
│ ├── vertical.sql
│ └── ...
└── dimensions.yaml # Конфигурация dimensions с метаданными
Связи между файлами:
sources/sources.yamlуказывает на:- SQL-файл в
sources/sql/(полеsql) -
Конфиги метрик в
metrics/(полеmetric_configs) -
Enrichments в
enrichments/применяются автоматически к source, еслиjoin_keyсовпадает -
Metrics в
metrics/могут использовать колонки из source и enrichments -
Dimensions в
dimensions/dimensions.yamlссылаются на SQL-справочники вdimensions/sql/
1. Sources — таблицы фактов#
Source — это SQL-запрос и метаданные в sources.yaml, которые описывают как извлекать исходные данные из DWH. Source возвращает таблицу фактов: события, даты, идентификаторы пользователей, дименшены и т. д.
# sources.yaml
buyer_stream:
sql: buyer_stream
metric_configs: [buyer_stream]
connections: [trino]
participant: {visitor: cookie_id, user: user_id}
dtm: event_date
-- sources/sql/buyer_stream.sql
SELECT cookie_id, event_date, eid, platform_id, events_count
FROM dwh.events
WHERE event_date BETWEEN :first_date AND :last_date
2. Enrichments — обогащения#
Enrichments добавляют новые колонки к source двумя способами:
1. Табличные enrichments (LEFT JOIN)
Обогащают данные через JOIN с другой таблицей. Например, добавление сегмента покупателя или источника трафика.
# enrichments/buyer_segment.yaml
buyer_segment_cookie:
sql: |
SELECT cookie_id, event_date, buyer_segment
FROM dma.v_buyer_segments
WHERE {{ pushdown_filter(cookie_id='cookie_id') }}
join_key: [cookie_id, event_date]
2. Calculated fields (вычисляемые поля)
Создают новые колонки на основе существующих через SQL-выражения, без JOIN.
# enrichments/calculated_fields.yaml
calculated_fields:
is_mobile: "platform_id IN (4, 14)"
price_bucket: |
CASE
WHEN price < 1000 THEN 'low'
WHEN price < 10000 THEN 'medium'
ELSE 'high'
END
Автоматическое применение:
Никаких явных связей настраивать не нужно. Enrichment становится доступен автоматически, если:
- Для табличных: в source есть все колонки из join_key
- Для calculated fields: в source есть все колонки из sql-выражения
При этом enrichment применяется только когда его колонки реально используются в запрошенных метриках или дименшенах.
3. Enriched Source — обогащенный источник#
Enriched Source — это не отдельная сущность для настройки, а концепция для понимания потока данных. Это результат объединения Source и Enrichments: виртуальная таблица с исходными колонками (cookie_id, event_date, eid) и добавленными колонками из enrichments (buyer_segment, traffic_source).
Вы настраиваете Source и Enrichments, а Enriched Source формируется автоматически. Enrichments добавляются в SQL только когда их колонки используются — это позволяет избежать лишних JOIN.
-- Enriched Source (концептуально)
WITH enriched AS (
SELECT
s.*, -- Исходные колонки
bs.buyer_segment -- Добавленная колонка (только если нужна)
FROM source s
LEFT JOIN buyer_segments bs -- Только если buyer_segment используется
ON s.cookie_id = bs.cookie_id
)
SELECT ... FROM enriched -- Metrics и Dimensions читают отсюда
4. Metrics — логика расчета#
Metrics описывают бизнес-логику метрик декларативно через фильтры. Они читают данные из Enriched Source и могут использовать как исходные колонки из source, так и добавленные колонки из enrichments.
Три типа метрик образуют иерархию: Counter (базовый подсчет) → Uniq (уникальные значения) → Ratio (производные метрики).
metric.counter:
purchases: {filter: [eid: 500]}
seeker_purchases: {filter: [buyer_segment: 'seeker', eid: 500]} # Добавленная колонка
metric.uniq:
buyers: {counter: purchases, key: [cookie_id]}
metric.ratio:
conversion: {num: buyers, den: daily_active_users}
5. Dimensions — разрезы#
Dimensions определяют разрезы для группировки метрик в A/B-тестах и M42. Как и метрики, они читают из Enriched Source и могут использовать любые колонки — и исходные из source, и добавленные из enrichments.
platform: # Исходная колонка (platform_id из source)
has_id: true
description: "Платформа (mobile, desktop)"
buyer_segment: # Добавленная колонка (из enrichment)
has_id: false
description: "Сегмент покупателя"
6. Trisigma Semantic Engine — генерация SQL#
Trisigma Semantic Engine — это центральный компонент, который на основе конфигов описанных пользователем конфигов генерирует оптимальный SQL-код.
Примеры задач:
Adhoc Queries — разовые запросы для анализа метрик. Используется для быстрой проверки данных и экспериментов.
trisigma sl compile --metrics conversion --dimensions platform
Experiment Reports — отчеты по A/B-тестам. Engine генерирует SQL для расчета метрик по группам эксперимента с учетом статистической значимости.
M42 — многомерные кубы для срезов данных. Формируются предрасчитанные данные в кубах дименшенов для быстрого анализа.
Datamarts/Datasets — витрины данных для регулярного использования. Engine создает материализованные денормализованные таблицы с предрасчитанными метриками для любых целей.
Пример: конверсия в покупку#
Рассмотрим как описать конверсию из просмотров в покупки.
1. Source — таблица фактов#
Source извлекает события пользователей с идентификаторами и типами событий:
SELECT cookie_id, event_date, eid, platform_id
FROM dwh.events
WHERE event_date BETWEEN :first_date AND :last_date
2. Enrichment — добавляем сегмент#
Enrichment добавляет колонку buyer_segment:
buyer_segment_cookie:
sql: SELECT cookie_id, event_date, buyer_segment FROM ...
join_key: [cookie_id, event_date]
3. Metrics — логика расчета#
Описываем метрики декларативно:
metric.counter:
views: {filter: [eid: 303]}
purchases: {filter: [eid: 500]}
metric.uniq:
viewers: {counter: views, key: [cookie_id]}
buyers: {counter: purchases, key: [cookie_id]}
metric.ratio:
conversion: {num: buyers, den: viewers}
4. Как это работает#
Без enrichment (колонка buyer_segment не используется):
SELECT
COUNT(DISTINCT CASE WHEN eid = 303 THEN cookie_id END) as viewers,
COUNT(DISTINCT CASE WHEN eid = 500 THEN cookie_id END) as buyers
FROM source
-- Нет LEFT JOIN с enrichment
С enrichment (группировка по buyer_segment):
WITH enriched AS (
SELECT s.*, e.buyer_segment
FROM source s
LEFT JOIN buyer_segment_enrichment e
ON s.cookie_id = e.cookie_id
AND s.event_date = e.event_date
)
SELECT
buyer_segment,
COUNT(DISTINCT CASE WHEN eid = 303 THEN cookie_id END) as viewers,
COUNT(DISTINCT CASE WHEN eid = 500 THEN cookie_id END) as buyers
FROM enriched
GROUP BY buyer_segment
Enrichment с buyer_segment применился автоматически, потому что колонка используется в GROUP BY.
(Это упрощенный пример, реальный SQL сложнее).
Для дальнейшего изучения#
- Sources — источники (таблицы фактов)
- Enrichments — обогащения
- Metrics — метрики
- Dimensions — разрезы
- Workflow — практика