Перейти к содержанию

Основные концепции#

Семантический слой состоит из четырех основных компонентов, которые вы настраиваете декларативно в 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 с метаданными

Связи между файлами:

  1. sources/sources.yaml указывает на:
  2. SQL-файл в sources/sql/ (поле sql)
  3. Конфиги метрик в metrics/ (поле metric_configs)

  4. Enrichments в enrichments/ применяются автоматически к source, если join_key совпадает

  5. Metrics в metrics/ могут использовать колонки из source и enrichments

  6. 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 сложнее).


Для дальнейшего изучения#