Зачем: владеть хотя бы одним 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>
9.1 KiB
Учебные задания: витрины слоя DM и дашборд в Superset
Пять домашних заданий — про витрины слоя DM. Стенд привозит слой наполовину: витрины трех сюжетов дашборда и контроль качества построены, остальные витрины строит менти. Каждое из них — самостоятельное ТЗ: что за витрина, какое у нее зерно, из чего она собирается и как проверить, что собралась верно.
Шестое задание — необязательная лаба в Superset. В ней менти собирает свой дашборд поверх пяти витрин.
Общее устройство слоя — дока DM. Она отвечает на вопросы «почему так», задание отвечает на вопрос «что сделать».
Порядок
Задания идут по нарастанию: каждое следующее опирается на то, что уже усвоено.
| № | Результат | Чему учит |
|---|---|---|
| 1 | events_enriched_v |
слой — это контракт, а не копия данных |
| 2 | top_pages_daily |
зерно сменилось — витрина материализуется и встает в конвейер |
| 3 | session_overview |
зерно решает, на какие вопросы витрина уже не ответит |
| 4 | dq_errors_daily |
у брака свой день и свой срок жизни |
| 5 | utm_effectiveness |
declared_ в имени — предупреждение, а не украшение |
| 6 | Свой дашборд в Superset — необязательная лаба | свои объекты BI живут отдельно от стендовых |
Общие правила
Они одни для пяти заданий по витринам, поэтому записаны здесь, а не повторяются в каждом ТЗ.
Читать — через _v. Публичный договор сущности DDS — представление с
суффиксом _v: dds.event_v, dds.session_v. Витрина называет только
его; физические _rep и _dist служат загрузке и обслуживанию. Соседнюю
домашку витрина источником тоже не берет: витрина слоя DM читает договор
DDS, и задания остаются независимыми. Исключение одно и оно оговорено в
задании 4: у таблиц брака публичного договора нет.
Писать — только в _dist. При записи в локальную таблицу раскладку
определяет то, какая нода случайно выполняла код, а не свойство данных.
Правило и его следствия — дока хранилища,
«Раскладка по шардам».
Форма — по зерну. Витрина, меняющая зерно источника, материализуется:
dm.<имя>_rep / _dist, донор dm.<имя>_stage_rep / _stage_dist и
публичное dm.<имя>_v с явным списком колонок. Витрина, сохраняющая зерно,
остается обычным представлением. Довод — дока DM,
«Форма: по зерну, не по цене запроса».
Ключ шардирования — твое решение. Ни одно ТЗ ключа не называет.
Правило выбора и требование к донору — дока
хранилища, «Раскладка по шардам»: донор
объявляется через AS <цель>_rep и шардируется тем же ключом, что цель,
иначе замена партиции потеряет строку на одном шарде и задвоит на другом.
Названный ключ надо уметь защитить: почему он не дает перекоса и почему
более сложный тут ничего не добавляет. Образец такой защиты —
dm.revenue_daily_dist в sql/ddl/55-dm-tables.sql.
Где лежит код. DDL домашек — свой файл sql/ddl/70-labs.sql: он
применяется после стендовых по порядку имени, и твои объекты не мешаются
со стендовыми. У агрегатов рядом со стендовыми ложатся еще три запроса —
sql/dm/<витрина>_scope.sql спрашивает у хранилища, какие дни пересобирает
запуск, _rebuild.sql собирает их в донор, _replace.sql заменяет
партицию, — и задача в
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 и запросы в sql/dq/.
Предупреждение. Запросы самой проверки лежат в sql/dq/ открыто, и
имена называют витрину и роль сверки. Проверка на инвариантах неизбежно
близка к ответу: чтобы сверить витрину, надо ее пересчитать. Прятать эти
файлы никто не станет — но открыв их до того, как задание сделано, ты
обменяешь урок на готовый SQL.
Смотреть туда стоит после своей сборки: сравнить два решения полезно,
списать одно — нет.
Уборка
Черновики и опыты за собой сносить: правило проверок стенда —
дока тестирования. Снесенная витрина обязана
снова покраснить свою задачу в homework_check — если не покраснила,
проверка ничего и не проверяла.