docs(labs): упрощен язык учебных заданий
- Зачем: начинающим трудно читать задания из-за необъясненных терминов и неестественных формулировок. - Что: переработаны вводная и 21 задание, названы темы разделов, объяснены термины и сокращены повторы; согласованы правила учебного текста и ссылки. - Проверка: сохранены 25 блоков SQL и команд и таблицы состава колонок; проверены 153 локальные ссылки и 32 входящие ссылки на разделы; git diff --check прошел.
This commit is contained in:
1 parent
3c3eb825e1
commit
4693bc5af9
24 files changed
+782
-684
No files matched your search
+124
-98
@@ -1,84 +1,121 @@
|
||||
# Учебные задания
|
||||
|
||||
Программа состоит из двух частей: основная включает семь ступеней, которые вы
|
||||
проходите по порядку, а факультативы выбираете по желанию. Причины такого
|
||||
порядка и формы заданий описаны в [программе учебных лаб](../specs/2026-09-01-labs-program.md#2-устройство-программы-основная-программа-и-факультативы).
|
||||
Вы будете достраивать хранилище небольшого интернет-магазина. Стенд уже
|
||||
загружает события сайта и заказы, обрабатывает их и строит несколько отчетов.
|
||||
Сначала вы подготовите данные для новых отчетов, затем разберетесь, как
|
||||
работают расчеты и загрузка, и перепишете часть из них.
|
||||
|
||||
## Основная программа
|
||||
Основная программа состоит из семи ступеней. Проходите их по порядку,
|
||||
факультативы выбирайте по желанию. Перед первым заданием прочитайте главу
|
||||
[«Хранилище и его слои»](../handbook/storage-layers.md) и выполните запросы
|
||||
из нее: они покажут данные, с которыми предстоит работать.
|
||||
|
||||
| Ступень | Задание | Чему учит |
|
||||
## Порядок заданий
|
||||
|
||||
| Ступень | Задания | Содержание |
|
||||
|---|---|---|
|
||||
| 1 | Пять витрин слоя DM | построить результат для потребителя хранилища; уроки каждой витрины — в таблице ниже |
|
||||
| 2 | [Свой график в Superset](2-1-superset-chart.md) | превратить свой результат из хранилища в отчет в BI |
|
||||
| 3 | [Нарежьте сессии сами](3-1-sessions-by-hand.md) | сверить число сессий в своей нарезке с эталоном и найти события, из-за которых оно расходится |
|
||||
| 4 | [Перепишите нарезку стенда](4-1-session-pipeline.md) | переписать расчет сессий в готовом конвейере и проверить по исходным событиям |
|
||||
| 5 | [Научите проверки замечать ошибки в заказах](5-1-order-checks.md)<br>[Перепишите разбор заказов в ODS](5-2-order-parsing.md)<br>[Перепишите сборку заказов в DDS](5-3-order-pipeline.md) | написать проверки качества до рискованного изменения, затем переписать разбор и сборку заказов |
|
||||
| 6 | [Разберите сырые события рядом со стендом](6-1-event-parsing.md) | изучить разбор потока отдельно от живого приема и сверить его со стендовым результатом |
|
||||
| 7 | [Мониторинг: куда смотреть](7-1-monitoring.md) | выбрать, куда и на что смотреть в живой системе |
|
||||
| 1 | Пять витрин для отчетов | подготовить данные о событиях, страницах, визитах, ошибках загрузки и рекламе; задания перечислены ниже |
|
||||
| 2 | [Свой график в Superset](2-1-superset-chart.md) | построить график по своей витрине и проверить числа на нем |
|
||||
| 3 | [Сессии из событий](3-1-sessions-by-hand.md) | объединить действия посетителя в визиты и сравнить их с визитами источника |
|
||||
| 4 | [Расчет сессий в стенде](4-1-session-pipeline.md) | включить свой расчет в готовую обработку данных и проверить результат |
|
||||
| 5 | [Проверки качества заказов](5-1-order-checks.md)<br>[Разбор заказов в ODS](5-2-order-parsing.md)<br>[Сборка заказов в DDS](5-3-order-pipeline.md) | сначала написать проверки качества, затем с их помощью проверить свою обработку заказов |
|
||||
| 6 | [Разбор сырых событий](6-1-event-parsing.md) | извлечь поля из сообщений и сравнить результат с готовым разбором стенда |
|
||||
| 7 | [Мониторинг: куда смотреть](7-1-monitoring.md) | найти тяжелые запросы и разобраться, почему данные обновляются с разной частотой |
|
||||
|
||||
## Ступень 1: пять витрин слоя DM
|
||||
## Ступень 1: витрины для отчетов
|
||||
|
||||
Слой DM в стенде построен наполовину: витрины трех сюжетов дашборда и контроль
|
||||
качества уже построены, остальные пять витрин строите вы. Каждая из них —
|
||||
самостоятельное задание: в нем есть состав витрины, зерно, источники и способ
|
||||
проверки.
|
||||
Витрина готовит данные для конкретного отчета. В стенде они находятся в базе
|
||||
`dm`: это слой DM. Витрины выручки, трафика, сверки покупок с заказами и
|
||||
сводка качества уже готовы. Вы добавите еще пять.
|
||||
|
||||
| № | Результат | Чему учит |
|
||||
| № | Витрина | Содержание задания |
|
||||
|---|---|---|
|
||||
| 1 | [`events_enriched_v`](1-1-events-enriched.md) | подготовить удобный для анализа набор полей, сохранив одну строку на событие |
|
||||
| 2 | [`top_pages_daily`](1-2-top-pages-daily.md) | создавать материализованную витрину с дневной пересборкой в конвейере |
|
||||
| 3 | [`session_overview`](1-3-session-overview.md) | хранить слагаемые для расчета средних и долей |
|
||||
| 4 | [`dq_errors_daily`](1-4-dq-errors-daily.md) | считать брак по дню загрузки и хранить итоги дольше источника |
|
||||
| 5 | [`utm_effectiveness`](1-5-utm-effectiveness.md) | читать `declared_` как предупреждение о сумме со слов клиента |
|
||||
| 1 | [События для анализа: `events_enriched_v`](1-1-events-enriched.md) | выбрать нужные поля и добавить вычисляемые, сохранив одну строку на событие |
|
||||
| 2 | [Показатели страниц по дням: `top_pages_daily`](1-2-top-pages-daily.md) | сохранить итоги в таблице и настроить их обновление через Airflow |
|
||||
| 3 | [Визиты по устройствам: `session_overview`](1-3-session-overview.md) | хранить суммы и счетчики для расчета средних и долей |
|
||||
| 4 | [Ошибки загрузки по дням: `dq_errors_daily`](1-4-dq-errors-daily.md) | сохранить число ошибок даже после удаления исходных строк |
|
||||
| 5 | [Показатели рекламы: `utm_effectiveness`](1-5-utm-effectiveness.md) | различать суммы покупок из событий сайта и выручку по заказам магазина |
|
||||
|
||||
Общее устройство слоя — [справочник DM](../architecture/dm.md). Он отвечает на
|
||||
вопросы «почему так», задание отвечает на вопрос «что сделать».
|
||||
Начните с [первого задания](1-1-events-enriched.md): для него достаточно
|
||||
одного представления. В заданиях 2–5 понадобятся таблицы и их обновление
|
||||
по дням. К общим правилам ниже возвращайтесь по мере работы.
|
||||
|
||||
## Как принято на ступени 1
|
||||
## Создание и обновление витрин
|
||||
|
||||
**Читать — через `_v`.** Физические `_rep` и `_dist` служат загрузке и
|
||||
обслуживанию, а публичный договор DDS — `dds.event_v` или `dds.session_v` —
|
||||
остается прежним даже при изменении физических объектов. Чтение DDS
|
||||
напрямую делает задания независимыми: соседняя витрина может быть еще не
|
||||
построена.
|
||||
Исключение — задание 4: у таблиц брака публичного договора нет.
|
||||
### Источники данных
|
||||
|
||||
**Писать — в `_dist`.** Так строки распределяются по ключу шардирования. При
|
||||
записи в локальную таблицу распределение зависит от узла, выполнившего
|
||||
запрос, и при следующем запуске может измениться. Подробности — раздел
|
||||
«Раскладка по шардам» [справочника хранилища](../architecture/storage.md).
|
||||
События читайте из `dds.event_v`, сессии из `dds.session_v`. Суффикс `_v`
|
||||
обозначает обычное представление: оно выполняет сохраненный запрос при
|
||||
чтении. Такие представления сохраняют привычные имена и состав колонок,
|
||||
когда внутреннее устройство таблиц меняется.
|
||||
|
||||
**Форма — по зерну.** На стенде агрегат с новым зерном принято хранить
|
||||
готовым: потребитель читает его много раз без повторного расчета по
|
||||
источнику. Создайте `dm.<имя>_rep` / `_dist`, донор `dm.<имя>_stage_rep` /
|
||||
`_stage_dist` и публичное `dm.<имя>_v` с явным списком колонок. При прежнем
|
||||
зерне достаточно представления: таблица дублировала бы данные. Доводы —
|
||||
раздел «Таблица или представление» [справочника
|
||||
DM](../architecture/dm.md).
|
||||
Каждая учебная витрина читает готовый источник и не зависит от других
|
||||
учебных витрин. В задании 4 источниками служат таблицы ошибок ODS:
|
||||
представлений для них нет.
|
||||
|
||||
**Ключ шардирования — ваше решение.** Объясните, почему выбранный ключ не
|
||||
дает существенного перекоса и почему более сложный ничего не добавит.
|
||||
Объявите донор через `AS <цель>_rep` с ключом цели: иначе замена партиции
|
||||
потеряет строку на одном шарде и удвоит на другом. Детали — раздел
|
||||
«Раскладка по шардам» [справочника хранилища](../architecture/storage.md).
|
||||
Пример обоснования — `dm.revenue_daily_dist` в
|
||||
### Таблицы и представления
|
||||
|
||||
В заданиях 2–5 вы группируете исходные строки. Например, в `top_pages_daily`
|
||||
одна строка содержит итоги для одной страницы за день. То, чему соответствует
|
||||
одна строка, называют **зерном**. На стенде итоги с новым зерном сохраняют
|
||||
в таблицах. Отчеты читают готовые числа.
|
||||
|
||||
Новый расчет сначала записывают в промежуточную таблицу. Пока он готовится,
|
||||
отчеты читают прежние данные из основной. Затем готовыми разделами
|
||||
промежуточной таблицы заменяют разделы основной. Раздел называется
|
||||
**партицией**; в этих заданиях он содержит данные одного дня.
|
||||
Промежуточную таблицу также называют **донором**.
|
||||
|
||||
На примере `top_pages_daily` пять объектов выглядят так:
|
||||
|
||||
| Объект | Для чего нужен |
|
||||
|---|---|
|
||||
| `dm.top_pages_daily_rep` | Хранит рассчитанные строки на каждом шарде |
|
||||
| `dm.top_pages_daily_dist` | Читает строки со всех шардов и распределяет запись между ними |
|
||||
| `dm.top_pages_daily_stage_rep` | Хранит новый расчет до замены данных в основной таблице |
|
||||
| `dm.top_pages_daily_stage_dist` | Распределяет запись нового расчета между шардами |
|
||||
| `dm.top_pages_daily_v` | Дает отчетам доступ к готовой витрине; явно перечисляет ее колонки |
|
||||
|
||||
### Распределение по шардам
|
||||
|
||||
Каждый из двух шардов стенда хранит свою часть данных. Записывайте строки
|
||||
через таблицы `_dist`: они выбирают шард по ключу шардирования. Прямая запись
|
||||
в `_rep` оставит строки на том узле, где выполнен запрос.
|
||||
|
||||
Ключ для своей витрины выберите сами. Проверьте распределение строк между
|
||||
шардами и объясните, почему выбранного ключа достаточно.
|
||||
Пример обоснования для `dm.revenue_daily_dist` есть в
|
||||
[`sql/ddl/55-dm-tables.sql`](../../sql/ddl/55-dm-tables.sql).
|
||||
|
||||
**Где лежит код.** DDL заданий — в `sql/ddl/70-labs.sql`.
|
||||
При создании мира он применяется после стендовых файлов.
|
||||
В уже работающем стенде сохранение файла и повторный `make up` новый DDL
|
||||
не применят — выполните его сами, как описано ниже. В
|
||||
`sql/dm/<витрина>_scope.sql` определяются дни прогона, в `_rebuild.sql` они
|
||||
собираются в донор, в `_replace.sql` заменяется партиция. Задачу сборки
|
||||
добавьте в [`dags/dm_transform.py`](../../dags/dm_transform.py): без нее
|
||||
конвейер не обновит витрину. Представлению достаточно `CREATE VIEW`.
|
||||
Создайте промежуточную таблицу через `AS <цель>_rep`, сохранив структуру и
|
||||
ключи основной. У обеих таблиц `_dist` должен быть одинаковый ключ
|
||||
шардирования: замена партиции выполняется внутри каждого шарда и не
|
||||
перераспределяет строки. Подробности есть в разделе
|
||||
[«Раскладка по шардам»](../architecture/storage.md#раскладка-по-шардам).
|
||||
|
||||
**Образец — витрина `revenue_daily`.** У нее есть пять объектов, донор,
|
||||
сборка, замена дневных партиций и задача в конвейере. Используйте ее как
|
||||
образец всего порядка пересборки. Состав колонок берите из своего ТЗ, иначе
|
||||
получите показатели другой витрины.
|
||||
### SQL-файлы и запуск расчета
|
||||
|
||||
## Как применить свой DDL
|
||||
Команды создания таблиц и представлений (DDL) сохраняйте в
|
||||
`sql/ddl/70-labs.sql`. При создании мира этот файл выполняется после
|
||||
стендовых файлов. В работающем стенде примените команды сами по инструкции
|
||||
ниже: сохранение файла и повторный `make up` их не выполнят.
|
||||
|
||||
Для витрины с таблицами нужны три файла в `sql/dm/`:
|
||||
|
||||
- `<витрина>_scope.sql` определяет, какие дни пересчитать;
|
||||
- `<витрина>_rebuild.sql` рассчитывает их и записывает в промежуточную таблицу;
|
||||
- `<витрина>_replace.sql` заменяет партицию одного дня в основной таблице.
|
||||
|
||||
Добавьте запуск расчета в [`dags/dm_transform.py`](../../dags/dm_transform.py),
|
||||
чтобы витрина обновлялась вместе с остальными. Для представления из задания 1
|
||||
достаточно выполнить `CREATE VIEW`.
|
||||
|
||||
Образец этого порядка работы есть у готовой витрины `revenue_daily`.
|
||||
Ее таблицы, SQL-файлы и задача Airflow разобраны в
|
||||
[справочнике DM](../architecture/dm.md#dmrevenue_daily_v).
|
||||
Состав колонок и выбор дней для пересчета берите из своего задания.
|
||||
|
||||
## Выполнение SQL в DBeaver
|
||||
|
||||
В DBeaver создайте подключение по [инструкции в README](../../README.md#подключиться-из-dbeaver),
|
||||
но укажите пользователя `etl` и пароль из `CLICKHOUSE_ETL_PASSWORD` в `.env`.
|
||||
@@ -88,37 +125,33 @@ DM](../architecture/dm.md).
|
||||
Создайте файл `sql/ddl/70-labs.sql` и сохраняйте в нем DDL своих витрин.
|
||||
Откройте его в SQL-редакторе этого подключения и выполните DDL текущего
|
||||
задания. Создавайте объекты с
|
||||
`ON CLUSTER clickstream_cluster`, чтобы они появились на обеих нодах;
|
||||
`ON CLUSTER clickstream_cluster`, чтобы они появились на обоих узлах;
|
||||
образец для представления — [`sql/ddl/60-dm-views.sql`](../../sql/ddl/60-dm-views.sql).
|
||||
Сохраненный файл позволит воссоздать ваши объекты при пересборке мира.
|
||||
|
||||
## Самопроверка ступени 1
|
||||
## Проверка витрин
|
||||
|
||||
Даг `homework_check` запускается руками, расписания у него нет. Задача
|
||||
витрины красная, пока витрины нет или счет не сходится, и зеленая, когда
|
||||
собрано верно. В сводку качества конвейера `dm.dq_summary` он не пишет: это
|
||||
инструмент лабы, а не история качества стенда.
|
||||
В Airflow есть даг `homework_check` с отдельной задачей для каждой учебной
|
||||
витрины. Запускайте его вручную: расписания у него нет. Задача завершится
|
||||
ошибкой, если витрина еще не создана или ее данные расходятся с ожидаемыми.
|
||||
Причину и примеры расхождений ищите в журнале задачи. Проверки еще не
|
||||
выполненных заданий тоже будут красными.
|
||||
|
||||
Для каждой витрины проверка независимо рассчитывает ожидаемый результат
|
||||
прямо по ее источнику. У четырех заданий источник
|
||||
эталона тот же, что у витрины, `dds.session_v` или `dds.event_v`; у задания
|
||||
4 это таблицы брака ODS, потому что в DDS нет сущности брака. Обе стороны
|
||||
соединяются по деловому ключу через `FULL OUTER JOIN`, и считается число
|
||||
строк, где стороны разошлись или одной стороны нет. Ноль — зеленый. Полное
|
||||
соединение сохраняет ключи обеих сторон: при внутреннем пропавший день или
|
||||
ключ не попал бы в результат, и потеря осталась бы незамеченной.
|
||||
Проверка заново рассчитывает показатели по источнику и сравнивает их с вашей
|
||||
витриной. Строки сопоставляются по полям, которые их определяют: например,
|
||||
по дню и странице. `FULL OUTER JOIN` позволяет найти и разные значения, и
|
||||
строки, которых нет с одной стороны. `INNER JOIN` пропустил бы отсутствующие
|
||||
строки. Когда расхождений нет, задача становится зеленой.
|
||||
|
||||
Раздел «Как проверить себя» каждого задания по витрине называет деловой ключ и
|
||||
сравниваемые величины. Тот же прием в стендовом исполнении — [даг
|
||||
`dq_check`](../../dags/dq_check.py) и запросы в [`sql/dq/`](../../sql/dq).
|
||||
`homework_check` не сохраняет результаты в сводку качества `dm.dq_summary`.
|
||||
|
||||
Запросы проверок лежат в `sql/dq/`. Откройте их после собственного решения:
|
||||
Запросы проверок лежат в [`sql/dq/`](../../sql/dq/). Откройте их после собственного решения:
|
||||
они заново рассчитывают показатели витрины, поэтому содержат ответ на
|
||||
существенную часть задания. Сравните свой способ расчета с готовым.
|
||||
|
||||
## Факультативы
|
||||
## Задания по желанию
|
||||
|
||||
Эти задания вы берете по желанию. Полный список сюжетов — в разделе
|
||||
Полный список сюжетов — в разделе
|
||||
[«Факультативы — пять разделов»](../specs/2026-09-01-labs-program.md#4-факультативы--пять-разделов)
|
||||
программы.
|
||||
|
||||
@@ -129,16 +162,17 @@ DM](../architecture/dm.md).
|
||||
- [Куда пропали покупки](optional/missing-purchases.md): найти заказы без
|
||||
события, выбрать источник витрины и условие проверки полноты.
|
||||
- [Почему повтор покупки завышает выручку](optional/duplicate-purchases.md):
|
||||
выбрать зерно и ключ расчета, проверить его на повторных событиях.
|
||||
рассчитать выручку с одной строкой на заказ и проверить результат на
|
||||
повторных событиях.
|
||||
- [Какая позиция объясняет разницу в сумме](optional/order-amount-difference.md):
|
||||
разобрать позиции без потери точности и локализовать расхождение источников.
|
||||
разобрать товары заказа без потери точности и найти причину разницы в суммах.
|
||||
- [Почему вчерашняя выручка меняется сегодня](optional/revenue-over-time.md):
|
||||
обосновать окно пересчета витрины и требования к истории заказов.
|
||||
определить, за какие дни пересчитывать выручку и какую историю заказов сохранять.
|
||||
|
||||
Первые три работы используют готовые данные. Четвертая продвигает мир через
|
||||
Airflow; для нее вы сохраняете состояния заказов после каждого модельного дня.
|
||||
|
||||
### Тонкий анализ данных
|
||||
### Данные о посетителях
|
||||
|
||||
Открывается после ступени 1.
|
||||
|
||||
@@ -146,9 +180,7 @@ Airflow; для нее вы сохраняете состояния заказо
|
||||
сохранить историю связей, сравнить расчеты на прежних сессиях и определить,
|
||||
какие сведения нужны для воспроизведения результата.
|
||||
|
||||
Обогащение отчета своим словарем регионов пока описано только в программе.
|
||||
|
||||
### Superset и BI
|
||||
### Отчеты в Superset
|
||||
|
||||
Открывается после ступени 2. Два самостоятельных задания:
|
||||
|
||||
@@ -157,21 +189,15 @@ Airflow; для нее вы сохраняете состояния заказо
|
||||
- [В DBeaver работает, в Superset нет](optional/superset-missing-object.md):
|
||||
выяснить, почему клиенты по-разному видят один объект хранилища.
|
||||
|
||||
### Инженерия стенда
|
||||
### Загрузка и обновление данных
|
||||
|
||||
Открывается после ступени 1. Прием и хранение данных, раскладка по шардам,
|
||||
повторная обработка дня и обновление витрин.
|
||||
Открывается после ступени 1.
|
||||
|
||||
- [Как обновлять витрину без полной пересборки](optional/incremental-daily-traffic.md):
|
||||
продолжить работу о связях пользователей, пересчитать затронутые дни
|
||||
и проверить повтор незавершенной загрузки. Повышенная сложность.
|
||||
|
||||
### Что делать, когда стенд сломался
|
||||
|
||||
Открывается после ступени 7. Поломки стенда и инструкции по восстановлению
|
||||
по итогам расследований; весь раздел — повышенная сложность.
|
||||
|
||||
## Уборка
|
||||
## Удаление временных объектов
|
||||
|
||||
После опытов удаляйте свои временные объекты. Если удалили учебную витрину,
|
||||
ее задача в `homework_check` должна снова завершиться ошибкой: отсутствие
|
||||
|
||||
Reference in new issue
Block a user