Files
clickstream-data-platform/docs/labs/README.md
T
ddadmin cffe1aeb73 docs(labs): обращение «вы» во всех учебных заданиях
- Зачем:
  - README и путеводитель обращаются к читателю на «вы», а ТЗ в docs/labs/
    были на «ты»; после пересборки индекса смесь стала заметна.
- Что:
  - во всех восьми файлах docs/labs/ местоимения, глаголы и повелительное
    наклонение переведены во второе лицо множественного числа.
  - названия ступеней в таблице README оставлены как в спеке.
- Проверка:
  - grep по формам «ты/твой», 'ё' и 'менти' по docs/labs/ молчит;
    git diff --check чистый; ревью диффа свежей сессией.
2026-09-03 17:29:13 -04:00

151 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Учебные задания
Программа состоит из двух частей: основная включает семь ступеней, которые вы
проходите по порядку, а факультативы выбираете по желанию. Причины такого
порядка и формы заданий описаны в [программе учебных лаб](../specs/2026-09-01-labs-program.md#2-устройство-программы-основная-программа-и-факультативы).
## Основная программа
| Ступень | Задание | Чему учит |
|---|---|---|
| 1 | Пять витрин слоя DM | построить результат для потребителя хранилища; уроки каждой витрины — в таблице ниже |
| 2 | [Свой график в Superset](superset-chart.md) | превратить свой результат из хранилища в отчет в BI |
| 3 | Нарежь сессии сам | счет показывает проблему, но причину приходится искать в отдельных строках |
| 4 | Перепиши нарезку стенда | изменить расчетную сущность внутри готового конвейера и проверить ее внешним эталоном |
| 5 | Сначала сторож, потом ломай: заказы | построить сторожей до рискованного изменения, а не после первой поломки |
| 6 | Разбери сырые события и сверь результат со стендом | изучить разбор потока отдельно от живого приема и сверить его со стендовым результатом |
| 7 | Мониторинг: куда смотреть | выбрать, куда и на что смотреть в живой системе |
ТЗ для ступеней 3–7 появятся по мере продвижения программы.
## Ступень 1: пять витрин слоя DM
Слой DM в стенде построен наполовину: витрины трех сюжетов дашборда и контроль
качества уже построены, остальные пять витрин строите вы. Каждая из них —
самостоятельное ТЗ: в нем есть состав витрины, зерно, источники и способ
проверки.
| № | Результат | Чему учит |
|---|---|---|
| 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_` в имени — предупреждение, а не украшение |
Общее устройство слоя — [дока DM](../architecture/dm.md). Она отвечает на
вопросы «почему так», задание отвечает на вопрос «что сделать».
## Общие правила ступени 1
Они одни для пяти заданий по витринам ступени 1, поэтому записаны здесь, а не
повторяются в каждом ТЗ.
**Читать — через `_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`: у нее есть все пять
объектов, донор, сборка, замена дневных партиций и задача в конвейере.
Списывать с нее устройство можно и нужно; списывать состав колонок — нет,
он у каждой витрины свой.
## Самопроверка ступени 1
Даг `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.
Смотреть туда стоит после своей сборки: сравнить два решения полезно,
списать одно — нет.
## Факультативы
Эти задания вы берете по желанию. Полный список сюжетов — в разделе
[«Факультативы — пять разделов»](../specs/2026-09-01-labs-program.md#4-факультативы--пять-разделов)
программы.
### Почему выручка не сходится
Открывается после ступени 1. Расхождения между источниками, повторы
покупок и день, после которого отчет можно считать окончательным.
### Тонкий анализ данных
Открывается после ступени 1. Знание о пользователе на дату и обогащение
отчета своим словарем.
### Superset и BI
Открывается после ступени 2. [Свой дашборд в Superset](superset-dashboard.md):
свои объекты BI живут отдельно от стендовых.
### Инженерия стенда
Открывается после ступени 1. Прием и хранение данных, раскладка по шардам,
повторная обработка дня и обновление витрин.
### Что делать, когда стенд сломался
Открывается после ступени 7. Поломки стенда и runbook по итогам
расследований; весь раздел — повышенная сложность.
## Уборка
Черновики и опыты за собой сносить: правило проверок стенда —
[дока тестирования](../architecture/testing.md). Снесенная витрина обязана
снова покраснить свою задачу в `homework_check` — если не покраснила,
проверка ничего и не проверяла.