Зачем: владеть хотя бы одним BI-инструментом на базовом уровне — полезный навык дата-инженера, но стенд в первую очередь про ClickHouse, поэтому лаба необязательная. Обещание «отдельная домашка после этапа 8» в доке DM висело без адреса. Что: ТЗ docs/labs/superset-dashboard.md — пять датасетов поверх публичных представлений заданий 1-5, свой дашборд отдельно от стендового, проверка глазами без homework_check; шестая строка и разведение «пяти заданий по витринам» в docs/labs/README.md; абзац о сроке жизни объектов менти в docs/architecture/superset.md; ссылка на лабу из доки DM; правило слага в AGENTS.md расширено до «предмет задания». Проверка: кода и DDL нет; слепое ревью текста (9 находок закрыто, 2 дополнительные с перепроверки) и финальная вычитка. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
110 lines
9.1 KiB
Markdown
110 lines
9.1 KiB
Markdown
# Учебные задания: витрины слоя DM и дашборд в Superset
|
||
|
||
Пять домашних заданий — про витрины слоя DM. Стенд привозит слой
|
||
наполовину: витрины трех сюжетов дашборда и контроль качества построены,
|
||
остальные витрины строит менти. Каждое из них — самостоятельное ТЗ: что за
|
||
витрина, какое у нее зерно, из чего она собирается и как проверить, что
|
||
собралась верно.
|
||
|
||
Шестое задание — необязательная лаба в Superset. В ней менти собирает свой
|
||
дашборд поверх пяти витрин.
|
||
|
||
Общее устройство слоя — [дока DM](../architecture/dm.md). Она отвечает на
|
||
вопросы «почему так», задание отвечает на вопрос «что сделать».
|
||
|
||
## Порядок
|
||
|
||
Задания идут по нарастанию: каждое следующее опирается на то, что уже
|
||
усвоено.
|
||
|
||
| № | Результат | Чему учит |
|
||
|---|---|---|
|
||
| 1 | [`events_enriched_v`](events-enriched.md) | слой — это контракт, а не копия данных |
|
||
| 2 | [`top_pages_daily`](top-pages-daily.md) | зерно сменилось — витрина материализуется и встает в конвейер |
|
||
| 3 | [`session_overview`](session-overview.md) | зерно решает, на какие вопросы витрина уже не ответит |
|
||
| 4 | [`dq_errors_daily`](dq-errors-daily.md) | у брака свой день и свой срок жизни |
|
||
| 5 | [`utm_effectiveness`](utm-effectiveness.md) | `declared_` в имени — предупреждение, а не украшение |
|
||
| 6 | [Свой дашборд в Superset](superset-dashboard.md) — необязательная лаба | свои объекты BI живут отдельно от стендовых |
|
||
|
||
## Общие правила
|
||
|
||
Они одни для пяти заданий по витринам, поэтому записаны здесь, а не
|
||
повторяются в каждом ТЗ.
|
||
|
||
**Читать — через `_v`.** Публичный договор сущности DDS — представление с
|
||
суффиксом `_v`: `dds.event_v`, `dds.session_v`. Витрина называет только
|
||
его; физические `_rep` и `_dist` служат загрузке и обслуживанию. Соседнюю
|
||
домашку витрина источником тоже не берет: витрина слоя DM читает договор
|
||
DDS, и задания остаются независимыми. Исключение одно и оно оговорено в
|
||
задании 4: у таблиц брака публичного договора нет.
|
||
|
||
**Писать — только в `_dist`.** При записи в локальную таблицу раскладку
|
||
определяет то, какая нода случайно выполняла код, а не свойство данных.
|
||
Правило и его следствия — [дока хранилища](../architecture/storage.md),
|
||
«Раскладка по шардам».
|
||
|
||
**Форма — по зерну.** Витрина, меняющая зерно источника, материализуется:
|
||
`dm.<имя>_rep` / `_dist`, донор `dm.<имя>_stage_rep` / `_stage_dist` и
|
||
публичное `dm.<имя>_v` с явным списком колонок. Витрина, сохраняющая зерно,
|
||
остается обычным представлением. Довод — [дока DM](../architecture/dm.md),
|
||
«Форма: по зерну, не по цене запроса».
|
||
|
||
**Ключ шардирования — твое решение.** Ни одно ТЗ ключа не называет.
|
||
Правило выбора и требование к донору — [дока
|
||
хранилища](../architecture/storage.md), «Раскладка по шардам»: донор
|
||
объявляется через `AS <цель>_rep` и шардируется тем же ключом, что цель,
|
||
иначе замена партиции потеряет строку на одном шарде и задвоит на другом.
|
||
Названный ключ надо уметь защитить: почему он не дает перекоса и почему
|
||
более сложный тут ничего не добавляет. Образец такой защиты —
|
||
`dm.revenue_daily_dist` в [`sql/ddl/55-dm-tables.sql`](../../sql/ddl/55-dm-tables.sql).
|
||
|
||
**Где лежит код.** DDL домашек — свой файл `sql/ddl/70-labs.sql`: он
|
||
применяется после стендовых по порядку имени, и твои объекты не мешаются
|
||
со стендовыми. У агрегатов рядом со стендовыми ложатся еще три запроса —
|
||
`sql/dm/<витрина>_scope.sql` спрашивает у хранилища, какие дни пересобирает
|
||
запуск, `_rebuild.sql` собирает их в донор, `_replace.sql` заменяет
|
||
партицию, — и задача в
|
||
[`dags/dm_transform.py`](../../dags/dm_transform.py). У разминочного
|
||
представления нет ничего из этого: весь его код — одно `CREATE VIEW`.
|
||
|
||
**Образец на все случаи** — витрина `revenue_daily`: у нее есть все пять
|
||
объектов, донор, сборка, замена дневных партиций и задача в конвейере.
|
||
Списывать с нее устройство можно и нужно; списывать состав колонок — нет,
|
||
он у каждой витрины свой.
|
||
|
||
## Самопроверка
|
||
|
||
Даг `homework_check` запускается рукой, расписания у него нет. Задача
|
||
витрины красная, пока витрины нет или счет не сходится, и зеленая, когда
|
||
собрано верно. В сводку качества конвейера `dm.dq_summary` он не пишет:
|
||
это инструмент лабы, а не история качества стенда.
|
||
|
||
Проверка пяти заданий по витринам устроена одинаково и золотых констант не
|
||
содержит: рядом с витриной независимым запросом собирается тот же ответ —
|
||
прямо из источника витрины, минуя ее саму. У четырех заданий источник эталона
|
||
тот же, что у витрины, `dds.session_v` или `dds.event_v`; у задания 4 это
|
||
таблицы брака ODS, потому что в DDS у брака представительства нет. Обе стороны
|
||
соединяются по деловому ключу через `FULL OUTER JOIN`, и считается число строк,
|
||
где стороны разошлись или одной стороны нет. Ноль — зеленый.
|
||
Полное соединение здесь обязательно: при обычном пропавший день или
|
||
пропавший ключ просто не попал бы в результат и остался бы незамечен.
|
||
|
||
Раздел «Как проверить себя» каждого ТЗ по витрине называет деловой ключ и
|
||
сравниваемые величины. Тот же прием в стендовом исполнении — [даг
|
||
`dq_check`](../../dags/dq_check.py) и запросы в [`sql/dq/`](../../sql/dq).
|
||
|
||
**Предупреждение.** Запросы самой проверки лежат в `sql/dq/` открыто, и
|
||
имена называют витрину и роль сверки. Проверка на инвариантах неизбежно
|
||
близка к ответу: чтобы сверить витрину, надо ее пересчитать. Прятать эти
|
||
файлы никто не станет — но открыв их до того, как задание сделано, ты
|
||
обменяешь урок на готовый SQL.
|
||
Смотреть туда стоит после своей сборки: сравнить два решения полезно,
|
||
списать одно — нет.
|
||
|
||
## Уборка
|
||
|
||
Черновики и опыты за собой сносить: правило проверок стенда —
|
||
[дока тестирования](../architecture/testing.md). Снесенная витрина обязана
|
||
снова покраснить свою задачу в `homework_check` — если не покраснила,
|
||
проверка ничего и не проверяла.
|