Зачем: путеводитель рассказывает путь данных через слои словами, а карта дает его увидеть и потрогать: у одного смысла в каждом слое свое имя и своя поверхность, а переносят данные три разных механизма — матвью непрерывно, даг пачкой, представление без копии. Постановка — тикет #222, форма — резолюция #208 (один самодостаточный HTML, исходники рядом). Что: docs/handbook/architecture-map.html — готовая карта; исходники в docs/handbook/architecture-map/ (map.yaml — слои, узлы, стрелки, карточки; template.html — разметка, стили, скрипт; render.py — сборка и --check; README.md). Щелчок по узлу открывает карточку и подсвечивает путь, щелчок по стрелке — кто и каким SQL переносит данные; переключатель потока приглушает чужую часть карты. Ссылки карточек ведут в справочники и DDL на Gitea. Путеводитель и глава о хранилище ведут на карту; make lint проверяет ruff для сборщика и свежесть рендера; testing.md и AGENTS.md обновлены. Проверка: uv run docs/handbook/architecture-map/render.py --check и make lint зеленые; внешних запросов в HTML нет; ссылки и якоря карточек сверены с Gitea; карта прощелкана в headless Chromium на ширинах 1280–1920: подсветка пути, фильтр, Esc, карточки узлов и стрелок. Ревью: постановка — Opus; реализация — Codex (Sol), два слепых ревью Opus (уместность и код), вычитка прозы Sol.
8.6 KiB
Хранилище и его слои
В хранилище приходят два потока из Kafka: в топике hits — события
кликстрима, в orders — заказы магазина. Оба проходят один путь: STG → ODS →
DDS → DM. Каждый слой отвечает на свой вопрос.
flowchart LR
Kafka --> STG --> ODS --> DDS --> DM
Как читать имена
Для обычного чтения выбирайте объекты с суффиксом _v. Это представления:
их устройство может поменяться, а ваш запрос останется прежним. Суффиксы
_rep, _dist, _kafka и _mv относятся к внутреннему
устройству хранилища. Они нужны для загрузки, обслуживания и диагностики.
У словарей есть исключение: у dic.products нет суффикса, потому что
различать нечего — объект один.
Подробный разбор имен есть в справочнике
хранилища.
STG: как поступило
STG — сырой слой. Он сохраняет сообщение целой строкой, без разбора. Рядом лежат метаданные доставки: топик, партиция, смещение и время приема. Поэтому в STG можно увидеть, что именно приехало из Kafka, даже если сообщение испорчено.
Срок хранения — трое суток реального времени. Этого хватает для расследования и повторного разбора, но старые строки не занимают диск вечно. Точное правило — в справочнике хранилища.
ODS: язык источника
ODS — слой разобранных данных. Строка получает типы: дата становится датой,
число — числом. Имена полей остаются на языке источника. Например, событие
сохраняет колонки WatchID, ClientID и EventDate.
Испорченное сообщение не останавливает загрузку. Оно попадает в таблицу
*_errors вместе с сырой строкой и классом ошибки. Так брак остается виден, а
годные строки продолжают движение.
DDS: язык бизнеса
DDS — детальный слой на языке бизнеса. Здесь есть событие, заказ, сессия и
карта идентичностей. Карта связывает посетителя, то есть куку ClientID, с
пользователем магазина из заказа.
Сессия не приходит готовой из Kafka. Стенд сам выделяет ее из последовательных событий одного посетителя. Здесь собраны сущности, с которыми дальше работают аналитики.
DM: данные для дашбордов
DM — слой витрин. Витрина — готовый набор показателей для отчета или дашборда. Здесь уже посчитаны, например, дневная выручка по категориям и дневные показатели трафика.
К каждой витрине можно обращаться коротким запросом, не повторяя в нем весь путь расчета. Состав готовых витрин смотрите в карте таблиц.
Сбоку цепочки: зона dic
Зона dic стоит вне пути STG → ODS → DDS → DM. В ней живут справочные данные,
которые хранилище получает готовыми. Ни один слой их не производит, а читать
может любой.
Первый справочник стенда — каталог товаров dic.products. Его ключ sku —
артикул товара. По нему можно узнать название, бренд и категорию товара. Как
устроена зона, смотрите в разделе о
справочниках.
Сквозные ключи
Один и тот же смысл проходит через слои под разными именами: имя меняется вместе с языком слоя. Таблица показывает исходное имя и то, где искать тот же смысл дальше.
| Колонка | Что означает | Что соединяет |
|---|---|---|
WatchID |
Идентификатор события | Событие ODS с событием DDS, где колонка называется event_id |
ClientID |
Посетитель, то есть кука | События ODS с событиями, сессиями и картой идентичностей DDS; в DDS колонка называется client_id |
order_id |
Идентификатор заказа | Заказ ODS с заказом DDS и витриной сверки dm.purchase_vs_orders_v |
sku |
Артикул товара в каталоге | Справочник dic.products с позициями заказа DDS, где артикулы лежат в item_sku; через категорию товара — с витриной выручки DM |
EventDate |
День на оси модельного времени, который счетчик сайта проставляет в своем часовом поясе | Событие ODS с событием DDS, где колонка называется event_date, и дневными расчетами DM |
Что здесь значит «посетитель» и чем кука отличается от человека, объясняет словарь понятий. Точные имена объектов и полей сверяйте с картой таблиц.
Посмотрите сами
Подключитесь к ClickHouse по инструкции из разделов «Адреса и
пароли» и «Подключиться из
DBeaver». В обоих примерах
2026-06-01 — это D0, первый день стартового
мира. Чтобы посмотреть другой день, замените
эту дату в условии. Первый запрос покажет
события одного модельного дня:
SELECT
WatchID,
ClientID,
EventDate,
EventType,
URL
FROM ods.event_v
WHERE EventDate = '2026-06-01'
ORDER BY UTCEventTime
LIMIT 20;
Второй запрос покажет готовую выручку по категориям за тот же день:
SELECT
product_category,
orders,
units,
revenue
FROM dm.revenue_daily_v
WHERE report_date = '2026-06-01'
ORDER BY revenue DESC;
Оба запроса читают поверхности _v. Первый показывает данные на языке
источника, второй — готовый ответ витрины.
Куда дальше
Откройте интерактивную карту из своей копии репозитория и проследите путь данных. Список объектов, сроки хранения и устройство таблиц — в справочнике хранилища. Как данные переносят между слоями — в следующей главе: потоки Airflow и даги модельного времени.