# Учебные задания Вы будете достраивать хранилище небольшого интернет-магазина. Стенд уже загружает события сайта и заказы, обрабатывает их и строит несколько отчетов. Сначала вы подготовите данные для новых отчетов, затем разберетесь, как работают расчеты и загрузка, и перепишете часть из них. Основная программа состоит из семи ступеней. Проходите их по порядку, факультативы выбирайте по желанию. Перед первым заданием прочитайте главу [«Хранилище и его слои»](../handbook/storage-layers.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)
[Разбор заказов в ODS](5-2-order-parsing.md)
[Сборка заказов в DDS](5-3-order-pipeline.md) | сначала написать проверки качества, затем с их помощью проверить свою обработку заказов | | 6 | [Разбор сырых событий](6-1-event-parsing.md) | извлечь поля из сообщений и сравнить результат с готовым разбором стенда | | 7 | [Мониторинг: куда смотреть](7-1-monitoring.md) | найти тяжелые запросы и разобраться, почему данные обновляются с разной частотой | ## Ступень 1: витрины для отчетов Витрина готовит данные для конкретного отчета. В стенде они находятся в базе `dm`: это слой DM. Витрины выручки, трафика, сверки покупок с заказами и сводка качества уже готовы. Вы добавите еще пять. | № | Витрина | Содержание задания | |---|---|---| | 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) | различать суммы покупок из событий сайта и выручку по заказам магазина | Начните с [первого задания](1-1-events-enriched.md): для него достаточно одного представления. В заданиях 2–5 понадобятся таблицы и их обновление по дням. К общим правилам ниже возвращайтесь по мере работы. ## Создание и обновление витрин ### Источники данных События читайте из `dds.event_v`, сессии из `dds.session_v`. Суффикс `_v` обозначает обычное представление: оно выполняет сохраненный запрос при чтении. Такие представления сохраняют привычные имена и состав колонок, когда внутреннее устройство таблиц меняется. Каждая учебная витрина читает готовый источник и не зависит от других учебных витрин. В задании 4 источниками служат таблицы ошибок ODS: представлений для них нет. ### Таблицы и представления В заданиях 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). Создайте промежуточную таблицу через `AS <цель>_rep`, сохранив структуру и ключи основной. У обеих таблиц `_dist` должен быть одинаковый ключ шардирования: замена партиции выполняется внутри каждого шарда и не перераспределяет строки. Подробности есть в разделе [«Раскладка по шардам»](../architecture/storage.md#раскладка-по-шардам). ### SQL-файлы и запуск расчета Команды создания таблиц и представлений (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`. Пользователь `analyst` из той инструкции предназначен для чтения; у `etl` есть права создавать таблицы и представления в `dm`. Создайте файл `sql/ddl/70-labs.sql` и сохраняйте в нем DDL своих витрин. Откройте его в SQL-редакторе этого подключения и выполните DDL текущего задания. Создавайте объекты с `ON CLUSTER clickstream_cluster`, чтобы они появились на обоих узлах; образец для представления — [`sql/ddl/60-dm-views.sql`](../../sql/ddl/60-dm-views.sql). Сохраненный файл позволит воссоздать ваши объекты при пересборке мира. ## Проверка витрин В Airflow есть даг `homework_check` с отдельной задачей для каждой учебной витрины. Запускайте его вручную: расписания у него нет. Задача завершится ошибкой, если витрина еще не создана или ее данные расходятся с ожидаемыми. Причину и примеры расхождений ищите в журнале задачи. Проверки еще не выполненных заданий тоже будут красными. Проверка заново рассчитывает показатели по источнику и сравнивает их с вашей витриной. Строки сопоставляются по полям, которые их определяют: например, по дню и странице. `FULL OUTER JOIN` позволяет найти и разные значения, и строки, которых нет с одной стороны. `INNER JOIN` пропустил бы отсутствующие строки. Когда расхождений нет, задача становится зеленой. `homework_check` не сохраняет результаты в сводку качества `dm.dq_summary`. Запросы проверок лежат в [`sql/dq/`](../../sql/dq/). Откройте их после собственного решения: они заново рассчитывают показатели витрины, поэтому содержат ответ на существенную часть задания. Сравните свой способ расчета с готовым. ## Задания по желанию Полный список сюжетов — в разделе [«Факультативы — пять разделов»](../specs/2026-09-01-labs-program.md#4-факультативы--пять-разделов) программы. ### Почему выручка не сходится Открывается после ступени 1. Четыре расследования качества данных: - [Куда пропали покупки](optional/missing-purchases.md): найти заказы без события, выбрать источник витрины и условие проверки полноты. - [Почему повтор покупки завышает выручку](optional/duplicate-purchases.md): рассчитать выручку с одной строкой на заказ и проверить результат на повторных событиях. - [Какая позиция объясняет разницу в сумме](optional/order-amount-difference.md): разобрать товары заказа без потери точности и найти причину разницы в суммах. - [Почему вчерашняя выручка меняется сегодня](optional/revenue-over-time.md): определить, за какие дни пересчитывать выручку и какую историю заказов сохранять. Первые три работы используют готовые данные. Четвертая продвигает мир через Airflow; для нее вы сохраняете состояния заказов после каждого модельного дня. ### Данные о посетителях Открывается после ступени 1. - [Как новые заказы меняют отчет о посетителях](optional/identity-over-time.md): сохранить историю связей, сравнить расчеты на прежних сессиях и определить, какие сведения нужны для воспроизведения результата. ### Отчеты в Superset Открывается после ступени 2. Два самостоятельных задания: - [Свой дашборд в Superset](optional/superset-dashboard.md): собрать отчет из своих витрин и подтвердить выводы запросами. - [В DBeaver работает, в Superset нет](optional/superset-missing-object.md): выяснить, почему клиенты по-разному видят один объект хранилища. ### Загрузка и обновление данных Открывается после ступени 1. - [Как обновлять витрину без полной пересборки](optional/incremental-daily-traffic.md): продолжить работу о связях пользователей, пересчитать затронутые дни и проверить повтор незавершенной загрузки. Повышенная сложность. ## Удаление временных объектов После опытов удаляйте свои временные объекты. Если удалили учебную витрину, ее задача в `homework_check` должна снова завершиться ошибкой: отсутствие витрины тоже проверяется. Подробнее — в [справочнике проверок](../architecture/testing.md).