Зачем: - Показать слой DDS как договор данных, которому не нужна физическая копия. - Сохранить простой учебный стенд без отдельного маршрута ради узких прав. Что: - Добавлено кластерное представление dds.event_v с явными 44 колонками. - Роли bi_reader разрешено чтение ODS, DDS и DM при договоре чтения через _v. - Согласованы мастер-спека, ADR, справочники архитектуры и живые тикеты этапа. - Зафиксировано исследование поведения DEFINER поверх Distributed. Проверка: - make config-test - make smoke - make check-clickhouse - Приёмочные запросы: равенство ODS/DDS, состав колонок, коды устройств и права bi.
13 KiB
Слой DM: витрины
Как модель DDS превращается в витрины для потребителя BI: какую форму принимает витрина, кто какие витрины строит и как слой проверяется. Состав колонок каждой витрины задаёт раздел 7 мастер-спеки; здесь — форма, наполнение и контроль.
Форма: по зерну, не по цене запроса
Витрина, меняющая зерно источника — дневной агрегат, сверка по заказам, —
материализуется: dm.<имя>_rep / _dist и публичное dm.<имя>_v с явным
списком колонок, по общим конвенциям хранилища. Наполняет её
dm_transform; ритм и механика пересборки — ниже. Витрина, сохраняющая зерно
источника — переименование, обогащение строки, — остаётся обычным
представлением: копию событий ради других имён колонок не держит ни один
боевой склад.
Правило выбрано учебной целью, а не ценой запроса. На объёмах стенда представлениями обошлось бы всё: условия сквозь цепочку представлений проходят (исследование). Но пересборка агрегатов конвейером — производственный паттерн, ради которого стенд и строится, а пара «таблица рядом с представлением» показывает: форма — решение по роли витрины, у одного слоя законны обе.
Кто строит: стенд и менти
Стенд привозит готовыми витрины трёх сюжетов дашборда этапа 8 и инфраструктуру контроля:
revenue_daily— выручка по дням и категориям; образец материализованной витрины, на него ссылаются учебные задания;purchase_vs_orders— сверка A+C с классами расхождений; зерно — заказ, шардирование сохраняет ко-локацию заказов поcityHash64(order_id);daily_traffic— пара «посетители» / «известные пользователи», локальное обогащение картой идентичностей;dq_summary— сводка проверок качества (ниже).
Остальные витрины спеки — учебные задания: менти строит их сам по ТЗ с
образцом. Разминка — представление events_enriched_v (зерно события),
затем агрегаты top_pages_daily, session_overview и dq_errors_daily,
последней — самая содержательная utm_effectiveness с уроком declared_*.
Построенная витрина встаёт в конвейер руками менти: финальный пункт
каждого ТЗ — добавить задачу своей витрины в dm_transform. До этого
конвейер о ней не знает и остаётся зелёным, после — витрина пересобирается
наравне со стендовыми.
Дашборд этапа 8 стоит только на витринах стенда: приёмка этапа не зависит от выполненных домашек. Расширение дашборда визуализациями по своим витринам — отдельная домашка после этапа 8.
Ритм пересборки
День витрины пересобирается, пока может измениться его источник, — поэтому ритмов три, по числу источников:
- от событий и сессий — день замерзает сразу; пересборка догоняет хвост несобранных дней заменой дневных партиций;
- от заказов — день дышит окном K и закрывается; пересборка заменяет партиции окна, дни за ним закрыты по построению;
- от карты идентичностей — не замерзает никогда: склейка ретроспективна, покупка сегодня делает куку известной во всех её прошлых днях, а карта пересчитывается целиком.
Поэтому daily_traffic наследует у своего источника и ритм, и механику:
полный пересчёт всех дней каждый прогон в ReplacingMergeTree(_load_ts),
как у самой карты. Дневных партиций у неё нет: партиция — единица замены,
а эта витрина заменяется только целиком. Пересчёт дешёв:
витрина читает сессии и карту локальным соединением по ключу ко-локации.
Пересчитывать точечно только затронутые дни не из чего: для этого надо
знать, какие связки новые, а полный пересчёт карты этот след затирает —
восстановление следа оставлено лабе повышенной сложности (issue #149).
dm.dq_summary
Зерно — «день данных × проверка»: строка отвечает, каково качество дня
сейчас, а не сколько раз его проверяли, — история прогонов и так живёт в
Airflow. Партиция — день данных; прогон звена DQ заменяет партиции
проверенных дней через REPLACE PARTITION. Обещанный спекой перевод с
TRUNCATE+INSERT выполняется той же механикой замены, что и у витрин, —
ничего отдельного учить не надо.
Звено DQ конвейера
Встаёт в etl_pipeline после DM (конвейер) и проверяет только
объекты стенда:
- счётная сверка сессий с эталоном
VisitID— кука × день, эталон читается изods.event_v(модель сессии); - счётчики классов расхождений против описи мира — по дням с закрытым окном. Проверка техническая, не урок DQ: её оракул — опись генератора, а у настоящего магазина оракула нет. Обещание узкое и честное: до витрин доехал тот мир, который родился, — одна растяжка через весь путь вместо сторожей на каждом шаге. Верно ли сам мир рождён, она не видит: опись считает тот же генератор;
- счётные сверки витрин стенда с их DDS-источниками.
Результаты ложатся в dm.dq_summary. Звено — не только сторож конвейера,
но и экспонат: менти видит, как контроль качества устроен в бою — по
расписанию, с историей, рядом с трансформациями.
Даг самопроверки
Домашки контролирует отдельный даг без расписания: менти запускает его
рукой. Задача витрины красная, пока витрины нет или счёт не сходится, и
зелёная, когда построено верно; сообщение об ошибке говорит, что не так и
куда смотреть. Проверки — инварианты против DDS-источников, золотые
константы не прибиваются. В dq_summary даг не пишет: он инструмент лабы,
а не история качества конвейера.
Приём проверен на соседнем учебном стенде Airflow + Greenplum: валидационный даг с группами проверок по слоям давал менти обратную связь по каждому шагу домашки, не трогая рабочий конвейер.
Остаётся нарезке
- Имена задач
dm_transform, звена DQ и дага самопроверки. - Ключи шардирования остальных материализованных витрин — вместе с их DDL; правило партиции-донора — в доке хранилища.
- Тексты учебных заданий и точный список проверок обоих контуров.
- Механика сверки A+C в SQL — рамка в спеке, разделы 4 и 7.
Отклонённые варианты
- Весь слой представлениями. Дёшево и всегда свежо, но главный
производственный паттерн слоя — пересборка агрегатов — остался бы
невидим, а
dm_transform— без работы. - Материализовать всё. Копия событий ради переименования колонок — антипаттерн, который менти увёз бы в бой.
- Гибрид по цене запроса. Выбор формы по стоимости, которой на объёмах стенда нет: сторож без настоящей опасности.
- Проверки домашек в конвейерном звене DQ. Конвейер стоял бы красным до выполнения лаб, а проверка, которая всегда красная, приучает себя игнорировать.
- «Жёлтый» статус недостроенной витрины. У задачи Airflow нет такого состояния; изображать его логами — семантика, которую пришлось бы расшифровывать. Красное «ещё не построено» честнее.
- Самопроверка пишет в
dq_summary. Попытки менти смешались бы с историей качества конвейера. - Окно K для
daily_traffic— прошлое замерзает. Дни за окном хранили бы число известных на момент закрытия — витрина тихо расходится с картой и протаскивает обратно «знание на дату», отвергнутое развилкой карты (#133). - Инкрементальный пересчёт затронутых дней по
first_matched_at. Производственный ход, но на объёмах стенда его экономия неизмерима, а след новых связок требует вернуть колонку, выкинутую в #133. Стал лабой повышенной сложности — issue #149. - Superset поверх DDS без слоя DM. Терялся бы урок «витрина — контракт под потребителя», против раздела 7 спеки.
Связанные решения
- Мастер-спека, разделы 4 и 7, — состав колонок витрин и классы сверки.
- Дневной конвейер — запуск
dm_transform, объём прогона, замена партиций на кластере. - Дока хранилища — имена объектов, конвенция чтения через
_v, партиция-донор. - Карта модели DDS — источники витрин.
- Резолюция — тикет #135 карты #127.