Files
clickstream-ch-kafka-supers…/docs/course/lessons/06_superset_bi.md
T
ddadmin bf940cc249 docs(course): пункт интро урока 6 выровнен под row-lineage
- Зачем:
  - после замены DQ-чарта на row-lineage в списке «на какие вопросы отвечает
    BI» остался повисший пункт «есть ли видимые проблемы качества данных» —
    чарта, который на него отвечал, больше нет.
- Что:
  - пункт переформулирован под актуальный чарт Rows by Layer
    («доходят ли строки до витрины без потерь по слоям конвейера»).
- Проверка:
  - сквозная вычитка урока 6: состав чартов, имена и числа согласованы.
2026-06-06 18:01:34 +03:00

22 KiB
Raw Blame History

Урок 6. BI-витрина в Superset

Формат: практика — будешь запускать Superset поверх готовых витрин ClickHouse, смотреть дашборд и делать маленькую обратимую правку в конфигурации чарта. Пререквизит: пройдены уроки 4–5 (ты уже запускал etl_pipeline, видел DM-слой в конце пайплайна и понимаешь разницу между мониторингом стенда и данными для анализа). Эталонные пути: sql/ddl/dm/40_dm.sql, sql/dm/40_dds_to_dm.sql, superset/init_superset.py, superset/create_dashboard.py.

Поток данных одной строкой: DDS → DM views / dm.dq_summary → Superset datasets → charts → dashboard → native filters

О чём урок простыми словами: ClickHouse уже подготовил таблицы и представления для потребления. Superset превращает их в экран для аналитика: датасеты, графики, фильтры и один общий дашборд.


1. Зачем и где в проде

После уроков 1–4 у нас есть данные: поток приземлился в STG, разобрался в ODS, собрался в DDS, а в конце появился DM-слой. После урока 5 у нас есть мониторинг: он отвечает, жив ли стенд и не сломался ли пайплайн.

Теперь нужен другой взгляд — BI (Business Intelligence, «аналитический интерфейс для бизнес-вопросов»). BI отвечает не «жив ли ClickHouse», а:

  • сколько событий пришло;
  • какие устройства чаще встречаются;
  • из каких стран пришёл трафик;
  • какие UTM-каналы дают больше кликов;
  • какие страницы самые популярные;
  • доходят ли строки до витрины без потерь по слоям конвейера.

Superset — BI-инструмент. Он не заменяет ClickHouse, Airflow или Grafana. Он сидит поверх готовых данных и даёт интерфейс для просмотра, фильтрации и сборки графиков.

В нашем стенде роли такие:

Слой Что делает
dds.click, dds.event хранит собранные сущности после ODS
dm.v_*, dm.dq_summary готовит поверхность потребления для аналитики
Superset dataset регистрирует таблицу или VIEW из ClickHouse в Superset
Superset chart сохраняет один график или KPI на базе dataset
Superset dashboard собирает charts в один экран
Native filters фильтруют dashboard по дате, стране, устройству, браузеру

Граница урока: витрина DM и BI-экран — не одно и то же.

DM-витрина — это SQL-объект в ClickHouse. Она задаёт форму данных: какие поля есть, на какой гранулярности лежит агрегат, какие joins уже сделаны. BI-экран — это способ показать эту витрину человеку: график, таблица, фильтр, порядок блоков на странице.

В проде иначе. Superset обычно подключают к нескольким хранилищам, заводят роли и права, разделяют черновые и опубликованные дашборды, а тяжёлые витрины материализуют. Но базовая схема та же: хранилище готовит данные, BI даёт удобную точку потребления.


2. Руки: запускаем Superset и смотрим дашборд

Подними стенд и прогони полный демо-датасет:

make up
make ddl
make data
make transform

make transform прогоняет цепочку STG → ODS → DDS → DM вне Airflow. Для этого урока так быстрее: нам нужен готовый DM-слой, а не разбор DAG. Отладочный срез через LIMIT=50 make data можно использовать для быстрых экспериментов, но эталонный dashboard и числа урока рассчитаны на полном наборе данных.

Теперь инициализируй Superset:

make superset-init

Эта команда создаёт или обновляет:

  • подключение clickhouse_dwh;
  • 6 datasets поверх dm.*.

После этого создай или обнови charts и сам dashboard:

make superset-dashboard

Эта команда создаёт или обновляет:

  • 10 charts;
  • dashboard E-commerce Analytics Dashboard.

Открой Superset: http://localhost:8088 (логин admin, пароль admin).

Если Superset предлагает сменить пароль после первого входа, для учебного стенда можно нажать Skip. В проде так не делают, но локальный курс держит одинаковые инструкции для всех.

Открываем dashboard

Открой готовый dashboard:

http://localhost:8088/superset/dashboard/1/

Если URL не открылся, зайди через меню Dashboards и найди E-commerce Analytics Dashboard.

На экране должны быть блоки:

  • KPI сверху: Total Events, Unique Users, Avg Events/Visit, Conversion to /confirmation;
  • динамика: Events over Time, Traffic by Device;
  • география: Geography Map;
  • маркетинг: UTM Effectiveness Table, Page Funnel;
  • прохождение строк по слоям: Rows by Layer (event).

Conversion to /confirmation считается как просмотры /confirmation / просмотры /home. Это page-funnel метрика, а не доля визитов: она совпадает с тем, как ниже устроен chart Page Funnel.

Rows by Layer (event) показывает, сколько строк доходит до каждого слоя конвейера STG → ODS → DDS → DM. Прежде чем читать чарт, договоримся про одно слово.

Зерно (grain), он же уровень гранулярности — это что считается одной строкой таблицы. У события зерно «одно событие = одна строка» (ключ event_id), у визита — «один визит = одна строка» (ключ click_id). Это разные зёрна: событий 1000, а визитов 99, потому что в одном визите много событий. Складывать строки разного зерна в одно число бессмысленно — это всё равно что сложить «штуки яблок» и «корзины яблок».

Поэтому чарт держит одно зерно — event: берёт по одной канонической таблице событий на слой (browser_raw → browser_event → event → v_events_enriched), а не сумму по слою. Если просуммировать все таблицы слоя, в один столбец попадут таблицы разного зерна (события 1000 + визиты 99 + пустые error-таблицы) и получится «воронка потерь», которой на самом деле нет.

Шаг 1050 → 1000 на первом переходе — это не потеря данных, а дедупликация at-least-once потока по event_id в ODS (ReplacingMergeTree): в STG приехало 1050 строк, но уникальных event_id среди них — 1000 (часть событий Kafka доставила повторно). Дальше число стабильно. Настоящие проблемы качества (ошибки парсинга, осиротевшие события) на чистых демо-данных равны нулю и лежат в dm.dq_summary отдельными check_name — их разбирали уроки 3–4.

Фильтр даты

В демо-данных события датированы 2022-11-28. В текущей конфигурации dashboard фильтр даты открывается как No filter. Если у тебя осталась старая metadata Superset и native filter Date Range стоит в значении Last week, часть графиков может быть пустой, хотя данные есть.

Для этого урока поставь в фильтре даты одно из двух:

  • No filter;
  • или ручной диапазон вокруг 2022-11-28.

После этого нажми Apply filters. Теперь смотри на dashboard как аналитик: какие графики отвечают на бизнес-вопросы, а какие только показывают техническое устройство конвейера.

Проверяем данные напрямую в ClickHouse

Открой ClickHouse play-консоль: http://localhost:9123/play.

Проверь, что основной dataset Superset не пустой:

SELECT count() AS events
FROM dm.v_events_enriched;

И посмотри, откуда берётся график Page Funnel:

SELECT page_url_path, sum(pageviews) AS pageviews
FROM dm.v_top_pages_daily
GROUP BY page_url_path
ORDER BY pageviews DESC
LIMIT 20;

Запомни эту связку: Superset показывает график, но данные и логика агрегации живут в ClickHouse.


3. Загляни внутрь

Разберём три места: DM-витрины в ClickHouse, регистрацию datasets в Superset и сборку charts / dashboard.

DM: поверхность потребления

Открой sql/ddl/dm/40_dm.sql.

В начале файла написано, почему DM сейчас сделан через VIEW:

  • логику можно менять без пересоздания таблиц;
  • нет копии данных поверх DDS;
  • для демо производительности достаточно.

Основная витрина для dashboard — dm.v_events_enriched. Она соединяет dds.event и dds.click через click_id:

FROM dds.event AS e
LEFT JOIN dds.click AS c ON c.click_id = e.click_id;

LEFT JOIN здесь осознанный: событие может существовать без части контекста из клика. Для BI это значит: график событий не исчезает только потому, что у части строк нет устройства или географии.

Другие VIEW дают более узкие поверхности:

VIEW / таблица Для чего нужна в Superset
dm.v_events_enriched KPI, динамика, устройства, география, фильтры
dm.v_daily_traffic готовая дневная агрегация трафика
dm.v_utm_effectiveness таблица по UTM-каналам
dm.v_top_pages_daily популярные страницы
dm.v_session_overview обзор сессий
dm.dq_summary метрики по слоям: строки (total_rows), ошибки, сироты

Открой sql/dm/40_dds_to_dm.sql. Этот файл не пересчитывает все dm.v_*: VIEW создаются в DDL. Здесь batch-часть наполняет dm.dq_summary метриками по слоям (включая строку для слоя dm), чтобы dashboard мог показать прохождение строк по конвейеру после каждого прогона.

init_superset.py: подключение и datasets

Открой superset/init_superset.py.

Сначала скрипт собирает URI ClickHouse:

return f"clickhousedb://{user}:{password}@{host}:{port}/{database}"

Внутри Docker-сети Superset ходит в ClickHouse по HTTP-порту 8123, поэтому URI использует clickhousedb://...@clickhouse:8123/default.

Потом скрипт создаёт подключение clickhouse_dwh и регистрирует datasets:

datasets = [
    {
        "table_name": "v_events_enriched",
        "schema": "dm",
        "database_name": "clickhouse_dwh",
        "description": "Полная обогащённая витрина событий (event + click)"
    },
    ...
]

Dataset в Superset — это не копия данных. Это запись в metadata Superset: какая таблица или VIEW есть в ClickHouse, какие у неё колонки и как её можно использовать в графиках.

Metadata Superset живёт в PostgreSQL, а сами данные остаются в ClickHouse. Поэтому после полного сброса volumes нужно заново создать metadata Superset, а после пересчёта данных — сами charts обычно остаются теми же.

create_dashboard.py: charts, dashboard, filters

Открой superset/create_dashboard.py.

В CHARTS_CONFIG лежит список charts. Один элемент списка — один график:

{
    "slice_name": "🪜 Page Funnel",
    "viz_type": "funnel",
    "dataset_name": "v_top_pages_daily",
    "params": {
        "groupby": ["page_url_path"],
        "metric": {
            "expressionType": "SQL",
            "sqlExpression": "SUM(pageviews)",
            "label": "Pageviews"
        },
        "row_limit": 20,
        "time_range": "No filter",
        "sort_by_metric": True,
        "percent_calculation_type": "first_step"
    }
}

Здесь видно четыре идеи:

  • slice_name — имя chart в Superset;
  • viz_type — тип визуализации;
  • dataset_name — на каком dataset строится chart;
  • params — настройка запроса и отображения.

Ниже DASHBOARD_CONFIG задаёт сам dashboard:

DASHBOARD_CONFIG = {
    "dashboard_title": "🛒 E-commerce Analytics Dashboard",
    "description": "...",
    "published": True,
    "slug": "ecommerce-analytics",
}

Dashboard находится по slug, а charts добавляются в layout. Если dashboard уже существует, скрипт обновляет metadata, layout и список charts. На этом держится управляемая правка: можно поменять параметр chart, запустить make superset-dashboard и увидеть результат в UI.

Native filters создаются в build_dashboard_metadata. Там есть фильтры:

  • Date Range по event_date;
  • Country по geo_country;
  • Device Type по device_type;
  • Browser по browser_name.

Что проверили по API. Перед уроком Superset сверили через MCP Context7 (/apache/superset): в Superset есть отдельные сущности charts и dashboards, metadata хранится отдельно от подключаемых источников данных. Для funnel Context7 не дал точную строку viz_type, поэтому дополнительно проверили установленный Superset 4.1.2: bundled example Featured Charts/Funnel.yaml использует viz_type: funnel. Поэтому в уроке не лезем в REST API Superset, а работаем через уже существующий скрипт стенда.


4. Управляемая правка: уменьшаем Page Funnel

Сейчас chart Page Funnel показывает до 20 страниц:

"row_limit": 20,

Сделай маленькую видимую правку: временно покажи только топ-3 страницы.

Открой superset/create_dashboard.py, найди chart Page Funnel и поменяй:

"row_limit": 20,

на:

"row_limit": 3,

Запусти обновление dashboard:

make superset-dashboard

Вернись в Superset и обнови страницу dashboard. В chart Page Funnel должно остаться не больше трёх страниц. Если фильтр даты снова скрыл данные, поставь Date Range → No filter и нажми Apply filters.

Почему это хорошая маленькая правка:

  • мы не меняем SQL-витрину в ClickHouse;
  • не создаём новый dataset;
  • не трогаем подключение к ClickHouse;
  • меняем только BI-представление уже готовых данных.

Верни как было

Верни в superset/create_dashboard.py:

"row_limit": 20,

И снова запусти:

make superset-dashboard

После обновления страницы chart Page Funnel снова может показывать до 20 страниц.

Если после экспериментов Superset выглядит странно, самый простой учебный возврат dashboard metadata к конфигурации из репозитория:

make superset-dashboard

Данные в ClickHouse эта команда не удаляет. Она повторно применяет charts и dashboard metadata Superset.


5. Проверь себя

Действие Где смотреть Что ожидать
make transform ClickHouse dm.v_events_enriched count() > 0
make superset-init Superset → Settings → Database Connections есть подключение clickhouse_dwh
открыть Datasets Superset UI есть datasets v_events_enriched, v_top_pages_daily, dq_summary
открыть dashboard Superset UI видны KPI, маркетинг, география и прохождение строк по слоям
поставить Date Range → No filter dashboard filters графики не скрываются из-за даты 2022-11-28
поменять row_limit у Page Funnel на 3 и запустить make superset-dashboard chart Page Funnel не больше трёх страниц
вернуть row_limit на 20 и запустить make superset-dashboard chart Page Funnel ограничение снова до 20 страниц

Вопросы для созвона:

  • чем DM-витрина отличается от Superset dataset;
  • почему Superset не должен ходить напрямую в сырые STG-таблицы;
  • зачем dashboard нужен Date Range, если SQL-витрина уже агрегирована;
  • почему изменение row_limit — это BI-правка, а не изменение модели данных;
  • где хранятся данные, а где metadata Superset.

6. Что должно получиться

К концу урока у тебя должен быть открытый dashboard E-commerce Analytics Dashboard в Superset. Сделай скриншот после временной правки Page Funnel: на нём должно быть видно, что chart показывает не больше трёх страниц.

Второй артефакт — короткий абзац своими словами:

DM-слой в ClickHouse готовит данные для потребления, dataset в Superset регистрирует эту витрину, chart задаёт один график, dashboard собирает charts в экран, а native filters дают аналитику быстрый способ менять срез данных.

После этого обязательно верни row_limit на 20, чтобы следующий урок или следующий прогон стенда начинался с исходной конфигурации.


Мост после курса

Теперь у тебя есть сквозная цепочка: Kafka → ClickHouse STG → ODS → DDS → DM → мониторинг → Superset. Следующий честный вопрос уже не про этот стенд, а про продакшен: какие витрины стоит материализовать, какие права дать BI-пользователям и как не превратить dashboard в единственный источник правды вместо версионированного SQL в репозитории.