diff --git a/docs/handbook/README.md b/docs/handbook/README.md index 76a16a6..331612d 100644 --- a/docs/handbook/README.md +++ b/docs/handbook/README.md @@ -1,50 +1,47 @@ # Путеводитель по стенду -Если вы впервые видите стенд, начните отсюда. Путеводитель подскажет, на что -смотреть и в каком порядке, а за подробностями отправит в справочники. Так вы -разберетесь в устройстве, прежде чем браться за уроки. +Путеводитель объясняет, как данные поступают в хранилище, обрабатываются +и попадают в отчеты. В главах есть короткие примеры, которые можно выполнить +на запущенном стенде перед переходом к учебным заданиям. ## Как читать -Тропа такая: [словарь понятий](../../CONTEXT.md) → главы путеводителя → -[справочники `docs/architecture/`](../architecture/) → -[уроки](../labs/README.md). - -Словарь не надо читать подряд. Возвращайтесь к нему за незнакомым словом. -Первая статья словаря объясняет хранилище. Следом идет несколько статей об -устройстве генератора; они понадобятся нескоро. +Читайте главы в порядке ниже. Незнакомые термины можно найти в +[словаре понятий](../../CONTEXT.md), а подробности устройства — +в [технических справочниках](../architecture/). К ним достаточно обращаться +по мере необходимости. После путеводителя переходите к +[учебным заданиям](../labs/README.md). ## Карта хранилища [Интерактивная карта](architecture-map.html) показывает путь данных через слои. Gitea показывает HTML как текст. Откройте файл из своей копии репозитория или скачайте его кнопкой «Raw» и откройте в браузере. -Держите карту рядом с главой «Хранилище и его слои». +Сверяйтесь с картой при чтении главы «Хранилище и его слои». ## Главы ### [Хранилище и его слои](storage-layers.md) -От события в Kafka до витрины: глава разбирает путь через STG, ODS, DDS и DM -и показывает, за что отвечает каждый слой. +Как меняются данные при переходе из Kafka в слои STG, ODS, DDS и DM. +В конце главы вы посмотрите события, сессии и выручку с помощью SQL. ### [Потоки Airflow и даги модельного времени](airflow-dags.md) -Шаговый даг играет модельный день, а дневной конвейер раскладывает данные по -слоям. Глава поможет увидеть их связь и роль каждого дага. +Какие даги создают новые данные, а какие обрабатывают их в хранилище. +Вы запустите генерацию и обработку за день и посмотрите результат в витринах. ### [Мониторинг: куда смотреть](monitoring.md) -Свежесть и поток данных, брак и отставание собраны на дашборде «Данные». -Глава научит находить нужную панель и разбирать ее показания. +Что показывают панели Grafana и как меняются их показания, пока в стенд +поступают события и заказы. ### [Немного Superset](superset.md) -Глава покажет, как витрина становится графиком и где проходит граница между -своими объектами и теми, которые поднимает стенд. +Как Superset строит графики по витринам и что происходит с вашими отчетами +при перезапуске стенда. ### [Генератор: откуда берутся данные](generator.md) -Здесь генератор — источник данных, а не предмет изучения. Глава в общих -чертах объяснит, откуда берутся события и заказы и в каком виде их получает -хранилище. +Откуда берутся события и заказы, почему начальные данные повторяются +и как сверить число загруженных событий с ожидаемым. diff --git a/docs/handbook/airflow-dags.md b/docs/handbook/airflow-dags.md index 2381c07..e21bdc9 100644 --- a/docs/handbook/airflow-dags.md +++ b/docs/handbook/airflow-dags.md @@ -1,7 +1,8 @@ # Потоки Airflow и даги модельного времени -В Airflow два рода дагов. Даги мира создают мир и проигрывают модельные дни, -а дневной конвейер раскладывает сыгранный день по слоям хранилища. +Airflow управляет генерацией данных и их обработкой в хранилище. Это разные +этапы: сначала в Kafka поступают события и заказы за день работы магазина, +затем по ним рассчитываются данные DDS и витрины DM. ```mermaid flowchart LR @@ -14,64 +15,72 @@ flowchart LR ## Два потока входят по-разному -События приходят в топик `hits`. Хранилище разбирает их само и непрерывно: +События поступают в топик `hits` и обрабатываются по мере поступления: материализованные представления переносят строки из STG в ODS без участия Airflow. -Заказы приходят в топик `orders` один раз в модельные сутки, целым слепком. У -слепка есть начало и конец, поэтому даг `orders_ingest` забирает его одной -порцией. Такой способ приема называется [пакетным](../../CONTEXT.md). +Заказы поступают в топик `orders` раз в модельные сутки одной выгрузкой. +Она содержит состояние заказов на конец дня и называется слепком. +Даг `orders_ingest` загружает ее целиком. Такой способ приема называется +[пакетным](../../CONTEXT.md). ## Даги мира -Два дага с тегом «жизненный цикл мира» отвечают за стартовый мир: +В документации миром называется учебный магазин с его посетителями, +товарами и заказами. Время в нем идет отдельно от календарного. +Два дага с тегом «жизненный цикл мира» создают начальные данные: | Даг | Что делает | |---|---| -| `world_initialize` | Создает стартовый мир, если его еще нет | -| `world_recreate` | Стирает данные мира и собирает стартовый мир заново | +| `world_initialize` | Создает начальные данные, если их еще нет | +| `world_recreate` | Удаляет прикладные данные и создает их заново | -Три дага с тегом «модельное время» проигрывают следующие дни. Именно их -называют дагами модельного времени. +Для добавления следующих дней есть три дага с тегом «модельное время»: | Даг | Что делает | |---|---| -| `world_next_day` | Играет следующие дни пачкой | -| `world_live_day` | Играет следующий день в темпе модельного времени | -| `world_live` | Запускает живые дни один за другим, пока снят с паузы | +| `world_next_day` | Генерирует данные за следующие дни без пауз между событиями | +| `world_live_day` | Генерирует данные за следующий день постепенно, примерно за 24 минуты | +| `world_live` | Запускает `world_live_day` день за днем, пока снят с паузы | -Сколько дней уже сыграно, стенд помнит в переменной Airflow `world_position`: -в ней лежит номер первого несыгранного дня. `world_next_day` и `world_live_day` -записывают новое значение только после успешно сыгранного дня; оборванный -прогон его не меняет. +В переменной Airflow `world_position` хранится номер следующего дня для +генерации. Например, при значении `8` генератор уже отправил события +за дни с 0 по 7. -Сыграв день D, эти два дага отправляют слепок заказов за день D−1 и ждут, пока -`orders_ingest` его примет. Эти связи разобраны в [справочнике -мира](../architecture/world.md#даги-модельного-времени). +`world_next_day` и `world_live_day` сначала отправляют события дня D, +затем — слепок заказов за предыдущий день D−1. Они ждут, пока `orders_ingest` +загрузит слепок, и только после успешного завершения дня обновляют +`world_position`. Если генерация или прием данных завершились с ошибкой, +номер дня остается прежним. Подробности — в [справочнике генератора +и модельного времени](../architecture/world.md#даги-модельного-времени). ## Дневной конвейер -У `etl_pipeline` нет своей обработки. Он по очереди запускает `dds_transform`, -`dm_transform` и `dq_check` и ждет каждый даг. Параметров у него нет: сколько -дней обработать, он сам определяет по `world_position` и по тому, что уже лежит -в слоях. Поэтому один и тот же запуск верен и когда его запустил другой даг, и -когда вы нажали кнопку, и когда его повторяют после сбоя. Детали есть в +Даг `etl_pipeline` по очереди запускает `dds_transform`, `dm_transform` +и `dq_check`, дожидаясь завершения каждого. Они рассчитывают данные DDS, +обновляют витрины DM и проверяют качество результата. + +При запуске `etl_pipeline` не нужно указывать даты. Дни для обработки +определяются по `world_position` и по уже загруженным данным в слоях. +Детали есть в [справочнике конвейера](../architecture/etl.md#объём-прогона). -`world_next_day` не запускает конвейер. После него слои хранилища отстают от -мира, пока вы не запустите конвейер сами. `world_live_day`, наоборот, -запускает `etl_pipeline` и ждет его. Поэтому даг остается в работе и после -конца модельного дня. +После `world_next_day` новые события и заказы уже загружены, но данные DDS +и DM еще не пересчитаны: запустите `etl_pipeline` вручную. +`world_live_day` запускает его автоматически и ждет завершения. Поэтому +`world_live_day` может продолжать работу после окончания генерации за день. -## Что значит красный +## Если даг завершился с ошибкой -Красный `etl_pipeline` не отменяет сыгранного дня: `world_position` уже -записана. Достаточно перезапустить конвейер рукой; разбираться, на чем -остановился прошлый прогон, не нужно. Кто запускает конвейер, описано в +Ошибка в `etl_pipeline` не меняет `world_position`: генерация и прием +данных за день уже завершились. После устранения причины ошибки +перезапустите конвейер вручную. Даты для повторной обработки он определит сам. +Кто запускает конвейер, описано в [разделе о трех путях запуска](../architecture/etl.md#три-пути-запуска). -Качество данных проверяет контур DQ. В дневном конвейере это даг `dq_check`: -упавшая задача печатает в лог ключи строк, не прошедших проверку. Состав +За качество данных отвечают проверки DQ (Data Quality) в даге `dq_check`. +Если проверка находит расхождение, задача завершается с ошибкой и записывает +в журнал ключи строк, которые ее не прошли. Состав проверок описан в [разделе «Звено DQ конвейера»](../architecture/dm.md#звено-dq-конвейера). @@ -87,8 +96,9 @@ Airflow. Откройте Airflow по адресу из раздела [«Адреса и пароли»](../../README.md#адреса-и-пароли). В Admin → Variables найдите `world_position`. Затем запустите `world_next_day` на один день по [инструкции -из README](../../README.md#добавить-данные-за-следующие-дни). Убедитесь, что `orders_ingest` -отработал, а витрины еще ничего не получили. Запустите `etl_pipeline` рукой. +из README](../../README.md#добавить-данные-за-следующие-дни). Убедитесь, что +`orders_ingest` завершился успешно, а в витринах нового дня еще нет. +Запустите `etl_pipeline` вручную и дождитесь его завершения. В DBeaver, подключенном по [инструкции](../../README.md#подключиться-из-dbeaver), выполните два запроса: @@ -106,9 +116,10 @@ ORDER BY report_date DESC LIMIT 3; ``` -В трафике уже есть сыгранный день, а в выручке только предыдущий: вместе с этим -днем пришел слепок заказов за предыдущий. Выручка сыгранного дня появится после -следующего. +В витрине трафика уже есть новый день, а в выручке последняя дата — +предыдущий день. Причина в выгрузке заказов: вместе с событиями дня D +приходит слепок за день D−1. Выручка дня D появится после генерации +дня D+1 и запуска конвейера. ## Куда дальше diff --git a/docs/handbook/generator.md b/docs/handbook/generator.md index ea97a5a..aadf9ac 100644 --- a/docs/handbook/generator.md +++ b/docs/handbook/generator.md @@ -1,42 +1,49 @@ # Генератор: откуда берутся данные -Генератор изображает две системы интернет-магазина. Первая — счетчик на сайте, -он шлет события в топик `hits`. Вторая — бэкенд магазина, он раз в модельные -сутки выгружает слепок заказов в топик `orders`. +Генератор имитирует работу двух систем интернет-магазина. Счетчик +на сайте отправляет записи о действиях посетителей в топик `hits`. Серверная часть +магазина раз в модельные сутки выгружает состояние заказов в топик `orders`. +Эта дневная выгрузка называется слепком. ## Что он производит -Событие — широкая строка по образцу выгрузки Яндекс Метрики. Генератор создает -три вида событий: просмотр страницы, корзину и покупку. Все колонки перечислены +Событие содержит сведения о действии посетителя: например, время, +адрес страницы и идентификатор посетителя. Формат соответствует образцу +выгрузки Яндекс Метрики. Генератор создает три вида событий: просмотр +страницы, добавление в корзину и покупку. Все колонки перечислены в [описании выгрузки](../formats/clickstream-event.md). -Заказ — та же покупка, но записанная бэкендом магазина, с суммами в деньгах. -Семь модельных дней после оформления заказ еще может измениться, поэтому каждый -дневной слепок несет заказы за последние семь дней в их текущем состоянии. -Устройство и форма слепка разобраны в [отдельном +Заказ содержит сведения о покупке со стороны магазина: товары, суммы +и состояние заказа. После оформления он еще может измениться, например +при отмене. Каждый дневной слепок содержит текущее состояние заказов, +оформленных за последние семь модельных дней. Состав и формат слепка +разобраны в [отдельном справочнике](../architecture/orders/snapshot.md). ## Почему данные всегда одни и те же -Генератор не берет случайность извне. Все его случайные решения выводятся из -[зерна](../architecture/generator/seeds.md) — одного числа в настройках — и из -номера дня. То же зерно и тот же номер дня дают ровно те же события, поэтому -стартовый мир одинаков при каждом `make up`. +Случайные решения генератора зависят от заданного числа — +[зерна генерации](../architecture/generator/seeds.md) — и номера дня. +При неизменных настройках и версии генератора одинаковые зерно и день +дают одинаковые события. Поэтому при создании стенда вы каждый раз +получаете те же начальные данные. Повторный `make up` на работающем стенде +сохраняет уже загруженные данные. -Рядом лежит паспорт мира, `data/world-inventory.json`: зерно, версия генератора -и по строке на каждый день с числом событий и контрольной суммой. По нему -проверяют, что генератор собрал тот же мир, что и раньше, и что в ODS все -доехало без потерь. Паспорт описывает только восемь дней стартового мира. +В файле `data/world-inventory.json` записаны зерно, версия генератора, +число событий и контрольная сумма за каждый из восьми начальных дней. +В документации этот файл называется паспортом мира. С ним можно сверить +результат генерации и проверить, все ли события загрузились в ODS. ## Кто его запускает На стенде генератором управляют [даги модельного времени](airflow-dags.md#даги-мира). Его можно запустить и напрямую. Команды -собраны в [справочнике мира](../architecture/world.md#как-запустить-генератор). +собраны в [справочнике генератора и модельного +времени](../architecture/world.md#как-запустить-генератор). -У генератора два режима. Пакетный отправляет весь день разом. Живой шлет -события по ходу модельных суток; сутки идут ускоренно и занимают около двадцати -четырех минут. +У генератора два режима. Пакетный отправляет все события дня без пауз. +В живом режиме события поступают постепенно, как в работающем магазине, +но время идет ускоренно: модельные сутки занимают около 24 минут. ## Посмотрите сами @@ -50,13 +57,14 @@ GROUP BY EventDate ORDER BY EventDate; ``` -Сравните первые восемь дней с восемью строками в [паспорте -мира](../../data/world-inventory.json): числа совпадут. Дни, сыгранные после -стартового мира, в паспорте не записаны. Так и задумано. +Сравните число событий за каждый из первых восьми дней со значением +`events` за ту же дату в [паспорте мира](../../data/world-inventory.json). +Числа должны совпасть. Если вы уже генерировали следующие дни, +в результате запроса будут дополнительные даты; в паспорте их нет. ## Куда дальше Подробнее генератор разобран в [README папки `generator/`](../../generator/README.md) и в [справочнике его -устройства](../architecture/generator/README.md). На этом путеводитель -заканчивается: дальше справочники и [учебные задания](../labs/README.md). +устройства](../architecture/generator/README.md). Теперь можно переходить +к [учебным заданиям](../labs/README.md). diff --git a/docs/handbook/monitoring.md b/docs/handbook/monitoring.md index fbbd82c..4b0be44 100644 --- a/docs/handbook/monitoring.md +++ b/docs/handbook/monitoring.md @@ -1,52 +1,61 @@ # Мониторинг: куда смотреть -В Grafana три дашборда, и у каждого своя тема. «Данные» показывает, все ли в -порядке с потоком данных. «Кластер» — состояние машин и самого ClickHouse. -«Запросы» — какие запросы выполнялись и сколько ресурсов они заняли. +В Grafana настроены три дашборда. «Данные» показывает загрузку и обработку +событий и заказов, «Кластер» — состояние узлов и самого ClickHouse, +а «Запросы» — выполненные запросы и затраченные на них ресурсы. -Prometheus собирает метрики с двух узлов ClickHouse, keeper и экспортера Kafka. -Grafana читает и Prometheus, и ClickHouse напрямую. На панелях нет порогов и -цветовой подсветки: оценивать картинку придется самому. Автоматические -проверки, которые выносят вердикт, собраны в контуре DQ. +Prometheus собирает метрики с двух узлов ClickHouse, ClickHouse Keeper +и экспортера Kafka — службы, которая предоставляет метрики Kafka. +Grafana получает данные из Prometheus и напрямую из ClickHouse. +На панелях не заданы пороги для цветовых предупреждений: оценивать показания +вы будете самостоятельно. Качество данных автоматически проверяет +даг `dq_check`. ## Дашборд «Данные» «Свежесть» показывает, сколько времени прошло с последнего события и с -последнего заказа в ODS. Свежесть заказов растет весь модельный день и -сбрасывается, когда на границе суток приходит слепок. Это нормальное поведение -источника, а не поломка. +последнего заказа в ODS. Показатель для заказов растет весь модельный день +и снижается, когда поступает очередная дневная выгрузка — слепок. +Это ожидаемо: заказы загружаются раз в день. «Поток» показывает число сырых сообщений в STG за выбранный интервал. «Брак» -рядом — доля строк, которые не удалось разобрать. +показывает долю строк, которые не удалось разобрать. «Сходимость» сравнивает число событий в Kafka и в ClickHouse. Тревожный -признак — устойчивый разрыв между линиями. Расхождение в одном столбце ничего -не значит. +признак — устойчивый разрыв между рядами. Разовое расхождение еще не говорит +о потере данных: метрики Kafka и строки ClickHouse могут попадать в соседние +интервалы на графике. «Отставание» показывает, сколько сообщений в Kafka еще не прочитано потребителями. «Дневной слепок» перечисляет последние десять слепков заказов в -STG: по нему видно, пришла ли выгрузка вовремя. +STG: по нему видно, поступила ли очередная выгрузка. Источники и правила чтения всех панелей разобраны в [справочнике дашборда «Данные»](../architecture/monitoring/data.md). ## Почему у панелей разные источники -Свежесть считается по ODS: если разбор остановился, это видно именно там. Поток -и брак считаются по STG, где сохраняется каждое доставленное сообщение. В ODS -повторы события и старые версии заказа схлопываются, поэтому счетчик там был бы -занижен. Подробности — в [разделе о слоях +Свежесть считается по ODS: если новые сообщения перестали разбираться, +показатель будет расти. Число поступивших сообщений берется из STG, +где сохраняются все сообщения, включая повторы. Для доли брака это число +сравнивается с числом строк в таблицах ошибок ODS. + +В основных таблицах ODS повторы событий и старые версии заказов удаляются +при слияниях. Поэтому число строк в них не подходит для подсчета +всех доставленных сообщений. Подробности — в [разделе о слоях панелей](../architecture/monitoring/data.md#почему-слои-у-панелей-разные). ## Два других дашборда -Открывайте «Кластер», когда нужно понять, что происходит с процессором, памятью -и дисками, с кусками данных и их слияниями в ClickHouse, с keeper или очередью -DDL. Устройство панелей описано в [справочнике дашборда +Открывайте «Кластер», чтобы проверить нагрузку на процессор, использование +памяти и дисков, число частей таблиц и ход их слияний в ClickHouse. Здесь же +показаны состояние ClickHouse Keeper и очередь распределенных DDL-команд. +Устройство панелей описано в [справочнике дашборда «Кластер»](../architecture/monitoring/cluster.md). -«Запросы» пригодится, когда вы ищете тяжелые запросы, ошибки или расход -ресурсов по пользователям. Как читать списки, объясняет [справочник дашборда +«Запросы» поможет найти медленные запросы, ошибки и пользователей, +чьи запросы потребляют много ресурсов. Как читать панели, объясняет +[справочник дашборда «Запросы»](../architecture/monitoring/queries.md). ## Посмотрите сами @@ -57,15 +66,18 @@ Airflow [`world_live_day`](airflow-dags.md#даги-мира): модельны около двадцати четырех минут. Смотрите свежесть событий и свежесть заказов по отдельности. Пока день идет, -свежесть событий держится на секундах, а свежесть заказов растет. На границе дня -слепок отправляется сразу: свежесть заказов сбрасывается, а свежесть событий -начинает расти, потому что новых событий до следующего дня не будет. Сам даг -остается в работе и после конца дня, потому что ждет дневной конвейер. +со времени последнего события проходят секунды, а время с последней +загрузки заказов растет. После завершения генерации событий отправляется +слепок заказов. Когда он загружен, показатель свежести заказов снижается. +Показатель для событий начинает расти: новые события поступят только +при генерации следующего дня. Даг пока продолжает работу, ожидая завершения +обработки данных в дневном конвейере. ## Куда дальше -Состав мониторинга собран в [справочнике -зоны](../architecture/monitoring/README.md), детали главного экрана — в -[справочнике дашборда «Данные»](../architecture/monitoring/data.md), а границы -решения — в [ADR 0002](../adr/0002-monitoring-scope.md). Следующая глава — +Устройство мониторинга описано в [техническом +справочнике](../architecture/monitoring/README.md), панели дашборда «Данные» — +в [отдельном разделе](../architecture/monitoring/data.md). +Почему выбраны именно эти показатели, объясняет +[ADR 0002](../adr/0002-monitoring-scope.md). Следующая глава — [«Немного Superset»](superset.md). diff --git a/docs/handbook/storage-layers.md b/docs/handbook/storage-layers.md index 780af86..b293734 100644 --- a/docs/handbook/storage-layers.md +++ b/docs/handbook/storage-layers.md @@ -2,7 +2,8 @@ В хранилище приходят два потока из Kafka: в топике `hits` — события кликстрима, в `orders` — заказы магазина. Оба проходят один путь: STG → ODS → -DDS → DM. Каждый слой отвечает на свой вопрос. +DDS → DM. В STG сообщения сохраняются как есть, в ODS разбираются по полям, +в DDS из них собираются события, заказы и сессии, а в DM — витрины для отчетов. ```mermaid flowchart LR @@ -11,54 +12,54 @@ flowchart LR ## Как читать имена -Для обычного чтения выбирайте объекты с суффиксом `_v`. Это представления: -их устройство может поменяться, а ваш запрос останется прежним. Суффиксы -`_rep`, `_dist`, `_kafka` и `_mv` относятся к внутреннему -устройству хранилища. Они нужны для загрузки, обслуживания и диагностики. -У словарей есть исключение: у `dic.products` нет суффикса, потому что -различать нечего — объект один. +Для обычного чтения выбирайте представления с суффиксом `_v`. Они позволяют +менять устройство таблиц, сохраняя привычные запросы к данным. +Суффиксы `_rep`, `_dist`, `_kafka` и `_mv` относятся к внутреннему устройству +хранилища. Эти объекты нужны для загрузки, обслуживания и диагностики. +У словаря товаров `dic.products` суффикса нет. Подробный разбор имен есть в [справочнике хранилища](../architecture/storage.md#имена-объектов). ## STG: как поступило -STG — сырой слой. Он сохраняет сообщение целой строкой, без разбора. Рядом -лежат метаданные доставки: топик, партиция, смещение и время приема. Поэтому в -STG можно увидеть, что именно приехало из Kafka, даже если сообщение -испорчено. +STG — сырой слой. Он сохраняет сообщение целой строкой, без разбора. Вместе +с ним записываются сведения о доставке: топик, партиция, смещение и время +приема. Содержимое сообщения сохраняется в STG, даже если в нем есть ошибки. -Срок хранения — трое суток реального времени. Этого хватает для расследования -и повторного разбора, но старые строки не занимают диск вечно. Точное правило -— в [справочнике +Сырые сообщения хранятся трое суток реального времени. В течение этого срока +их можно использовать для поиска ошибок и повторной обработки. Затем они +удаляются по правилу из [справочника хранилища](../architecture/storage.md#срок-жизни-сырых-данных). ## ODS: язык источника -ODS — слой разобранных данных. Строка получает типы: дата становится датой, -число — числом. Имена полей остаются на языке источника. Например, событие -сохраняет колонки `WatchID`, `ClientID` и `EventDate`. +В ODS содержимое сообщения разбирается на колонки с нужными типами данных: +датами, числами, строками. Колонки сохраняют имена из источника. Например, +в таблице событий есть `WatchID`, `ClientID` и `EventDate`. Испорченное сообщение не останавливает загрузку. Оно попадает в таблицу -`*_errors` вместе с сырой строкой и классом ошибки. Так брак остается виден, а -годные строки продолжают движение. +`*_errors` вместе с исходной строкой и классом ошибки. Правильно записанные +сообщения обрабатываются дальше. ## DDS: язык бизнеса -DDS — детальный слой на языке бизнеса. Здесь есть событие, заказ, сессия и -карта идентичностей. Карта связывает посетителя, то есть куку `ClientID`, с -пользователем магазина из заказа. +DDS — детальный слой: в нем данные подготовлены для анализа событий, +заказов и сессий. Здесь же хранится карта идентичностей — таблица связей +между идентификатором посетителя `ClientID` и пользователем магазина +из заказа. `ClientID` хранится в cookie браузера: по нему можно узнать +браузер посетителя, но не всегда самого человека. -В стенде визитом считают подряд идущие события одной куки без пауз -дольше 30 минут. Визит не пересекает границу модельных суток. -Аналитик называет такой визит сессией. +В стенде визитом, или сессией, считают подряд идущие события одного +`ClientID` без пауз дольше 30 минут. Визит не пересекает границу модельных суток. -В бою Метрика нарезает визиты сама и добавляет готовый `VisitID` в -события. Стенд играет ее роль: считает сессии из событий заново, а `VisitID` -оставляет эталоном для проверки. Иначе сборка сессий свелась бы к группировке -по чужому полю, и учиться было бы не на чем. Идентификатор сессии -`session_id` чеканит стенд: в событии его нет. Готовые сессии читайте через -`dds.session_v`. В `dds.event_v` поля `VisitID` нет: так сессии можно собрать -самому и сравнить с эталоном. +Источник передает готовый идентификатор визита `VisitID` по образцу +Яндекс Метрики. В учебном хранилище сессии рассчитываются заново по времени +событий; каждой присваивается `session_id`. Поле `VisitID` остается +эталоном для проверки. Так в заданиях вы сможете самостоятельно определить +границы сессий и сравнить их с результатом источника. + +Готовые сессии читайте через `dds.session_v`. События для самостоятельного +расчета доступны в `dds.event_v`: в этом представлении `VisitID` скрыт. ## DM: данные для дашбордов @@ -70,32 +71,31 @@ DM — слой витрин. Витрина — готовый набор по путь расчета. Состав готовых витрин смотрите в [карте таблиц](../architecture/storage.md#карта-таблиц). -## Сбоку цепочки: зона `dic` +## Справочные данные: зона `dic` -Зона `dic` стоит вне пути STG → ODS → DDS → DM. В ней живут справочные данные, -которые хранилище получает готовыми. Ни один слой их не производит, а читать -может любой. +В базе `dic` хранятся готовые справочные данные. Они загружаются отдельно +от событий и заказов и могут использоваться в расчетах любого слоя. -Первый справочник стенда — каталог товаров `dic.products`. Его ключ `sku` — +Каталог товаров `dic.products` — один из таких справочников. Его ключ `sku` — артикул товара. По нему можно узнать название, бренд и категорию товара. Как устроена зона, смотрите в [разделе о справочниках](../architecture/storage.md#справочники). ## Сквозные ключи -Один и тот же смысл проходит через слои под разными именами: имя меняется -вместе с языком слоя. Таблица показывает исходное имя и то, где искать тот же -смысл дальше. +Идентификаторы позволяют связать данные из разных слоев. При переходе в DDS +часть колонок переименовывается: например, `WatchID` становится `event_id`. +В таблице указано, как найти соответствующие колонки и соединить по ним данные. | Колонка | Что означает | Что соединяет | |---|---|---| | `WatchID` | Идентификатор события | Событие ODS с событием DDS, где колонка называется `event_id` | -| `ClientID` | Посетитель, то есть кука | События ODS с событиями, сессиями и картой идентичностей DDS; в DDS колонка называется `client_id` | +| `ClientID` | Идентификатор посетителя из cookie браузера | События ODS с событиями, сессиями и картой идентичностей DDS; в DDS колонка называется `client_id` | | `order_id` | Идентификатор заказа | Заказ ODS с заказом DDS и витриной сверки `dm.purchase_vs_orders_v` | | `sku` | Артикул товара в каталоге | Справочник `dic.products` с позициями заказа DDS, где артикулы лежат в `item_sku`; через категорию товара — с витриной выручки DM | -| `EventDate` | День на [оси модельного времени](../../CONTEXT.md), который счетчик сайта проставляет в [своем часовом поясе](../architecture/storage.md#часовые-пояса) | Событие ODS с событием DDS, где колонка называется `event_date`, и дневными расчетами DM | +| `EventDate` | Дата события в [модельном времени](../../CONTEXT.md), указанная счетчиком сайта в [его часовом поясе](../architecture/storage.md#часовые-пояса) | Событие ODS с событием DDS, где колонка называется `event_date`, и дневными расчетами DM | -Что здесь значит «посетитель» и чем кука отличается от человека, объясняет +Почему идентификатор посетителя не равнозначен человеку, объясняет [словарь понятий](../../CONTEXT.md#язык). Точные имена объектов и полей сверяйте с [картой таблиц](../architecture/storage.md#карта-таблиц). @@ -104,10 +104,10 @@ DM — слой витрин. Витрина — готовый набор по Подключитесь к ClickHouse по инструкции из разделов [«Адреса и пароли»](../../README.md#адреса-и-пароли) и [«Подключиться из DBeaver»](../../README.md#подключиться-из-dbeaver). Во всех трех примерах -`2026-06-01` — это D0, первый день [стартового -мира](../../CONTEXT.md). Чтобы посмотреть другой день, замените -эту дату в условии. Первый запрос покажет -события одного модельного дня: +`2026-06-01` — первый день работы учебного магазина. В документации он +обозначается D0; подробнее — в [словаре понятий](../../CONTEXT.md). +Чтобы посмотреть другой день, замените дату в условии. +Первый запрос покажет 20 событий за выбранный день: ```sql SELECT @@ -122,8 +122,8 @@ ORDER BY UTCEventTime LIMIT 20; ``` -Второй запрос покажет сессии того же дня. Они рассчитаны из событий -первого запроса: +Второй запрос покажет 20 сессий того же дня с наибольшим числом событий. +Сессии рассчитаны по всем событиям дня: ```sql SELECT @@ -153,14 +153,13 @@ WHERE report_date = '2026-06-01' ORDER BY revenue DESC; ``` -Все три запроса читают поверхности `_v`. Первый показывает данные на языке -источника, второй — расчетную сущность, третий — готовый ответ витрины. +Все три запроса читают представления `_v`. ## Куда дальше Откройте [интерактивную карту](architecture-map.html) из своей копии репозитория и проследите путь данных. Список объектов, сроки хранения и устройство таблиц — в [справочнике -хранилища](../architecture/storage.md). Как данные переносят между слоями — в +хранилища](../architecture/storage.md). Как данные обрабатываются между слоями — в следующей главе: [потоки Airflow и даги модельного времени](airflow-dags.md). diff --git a/docs/handbook/superset.md b/docs/handbook/superset.md index 412638b..79ab674 100644 --- a/docs/handbook/superset.md +++ b/docs/handbook/superset.md @@ -6,39 +6,44 @@ Superset показывает витрины слоя DM в виде графи | Витрина | Что показывает | |---|---| -| `dm.revenue_daily_v` | выручку, заказы и средний чек крупными числами, выручку по дням и категориям столбиками, доли категорий кольцом | -| `dm.purchase_vs_orders_v` | сводную сверки: сколько заказов дня попало в каждый класс расхождения | -| `dm.daily_traffic_v` | число посетителей крупно, посетителей и известных пользователей по дням, отдельно — долю известных | +| `dm.revenue_daily_v` | Выручку, число заказов и средний чек; выручку по дням и категориям товаров, долю каждой категории | +| `dm.purchase_vs_orders_v` | Результат сверки покупок из кликстрима с заказами: сколько заказов за день относится к каждому виду расхождения | +| `dm.daily_traffic_v` | Число посетителей и известных пользователей по дням, долю известных пользователей | + +Известные пользователи — те, кого удалось связать с посетителями сайта +по заказам. Эти связи хранятся в карте идентичностей DDS. Слева от панелей стоит фильтр «Период». Он задает даты сразу для всех панелей. ## Как витрина становится графиком -От витрины до экрана три объекта Superset: датасет → график → дашборд. Датасет -описывает витрину: задает русские имена колонок, формат чисел и показатели — -например, средний чек. График ссылается на эти имена и задает способ показа. -Дашборд собирает готовые графики на одном экране. +В Superset сначала создается датасет — описание таблицы или представления, +из которого будут браться данные. В нем задаются подписи колонок, формат +чисел и показатели, например средний чек. + +Затем на основе датасета создается график: выбираются показатели и способ +их отображения. Несколько графиков можно разместить на одном дашборде. ## Стендовые объекты и ваши -Датасеты, графики и дашборд из поставки стенда лежат файлами в репозитории и -заново импортируются при каждом `make up`. Если поправить такой объект в -интерфейсе, правка проживет до следующего `make up`, а потом без предупреждения -заменится версией из файла. +Готовые датасеты, графики и дашборд сохранены в файлах репозитория +и импортируются при каждом `make up`. Если изменить их через интерфейс, +следующий `make up` заменит изменения версией из файлов без предупреждения. -Ваши собственные объекты хранятся в той же базе метаданных Superset, но импорт -их не трогает: они переживают и `make up`, и `make rebuild-storage`. Стирает их -только `make clean` вместе с остальным постоянным состоянием стенда. Поэтому -стендовые объекты оставляйте как есть, а свои отчеты стройте рядом. Устройство +Созданные вами датасеты, графики и дашборды хранятся в базе метаданных +Superset. Импорт их не меняет: они сохраняются после `make up` +и `make rebuild-storage`. Команда `make clean` удалит их вместе со всеми +данными стенда. Для учебных отчетов создавайте собственные объекты, +чтобы повторный запуск не перезаписал вашу работу. Устройство импорта описано в [справочнике Superset](../architecture/superset.md#импорт-при-каждой-инициализации). -## Почему края графиков не совпадают +## Почему выручка отстает на день -Правый край графика выручки всегда на день позади графиков кликстрима. Слепок -заказов за день приходит только со следующим модельным днем. Так устроен -источник, а не витрина. Вы уже видели этот -сдвиг в [главе об Airflow](airflow-dags.md#посмотрите-сами). Начальное состояние +Последняя дата с выручкой на день раньше последней даты с событиями +кликстрима. Выгрузка заказов за день D поступает при генерации следующего +дня D+1, а затем обрабатывается конвейером. Вы уже видели эту разницу +в [главе об Airflow](airflow-dags.md#посмотрите-сами). Начальное состояние показано в разделе [«Стартовый мир»](../architecture/world.md#стартовый-мир). ## Посмотрите сами @@ -58,7 +63,7 @@ LIMIT 7; ## Куда дальше -Устройство BI-зоны описано в [справочнике +Подключение и настройка Superset описаны в [справочнике Superset](../architecture/superset.md), а состав витрин — в [справочнике DM](../architecture/dm.md). Следующая глава — [«Генератор: откуда берутся данные»](generator.md).