- Зачем:
- в docs/labs/ будет много заданий; номер ступени и номер задания в имени
делают папку оглавлением программы и избавляют от поиска по README (#230).
- Что:
- шесть ТЗ переименованы через git mv: 1-1…1-5 для ступени 1,
2-1-superset-chart.md для ступени 2; факультатив superset-dashboard.md
остался без номера.
- обновлены ссылки в docs/labs/README.md, 2-1-superset-chart.md,
docs/architecture/dds/session.md и пути в dags/homework_check.py.
- правило имен для docs/labs/ в AGENTS.md переписано под S-N-slug.
- Проверка:
- make lint; скрипт обхода относительных ссылок в docs/ и AGENTS.md —
битых нет.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
119 lines
8.1 KiB
Markdown
119 lines
8.1 KiB
Markdown
# Задание 3: `dm.session_overview`
|
||
|
||
**Чему учит:** хранить слагаемые, а не готовые средние и доли. Понимать,
|
||
почему сумма `visitors` по строкам сейчас сходится, но начнет завышать
|
||
аудиторию, если у одной куки появятся визиты с двух устройств.
|
||
|
||
## Сначала прочитать
|
||
|
||
- [«Хранилище и его слои»](../handbook/storage-layers.md);
|
||
- [«Потоки Airflow и даги модельного времени»](../handbook/airflow-dags.md).
|
||
|
||
## Роль витрины
|
||
|
||
Витрина нужна, чтобы по дням сравнивать визиты с телефона и компьютера: их
|
||
число, длительность, просмотры страниц и частоту покупок.
|
||
|
||
На прошлом стенде витрина выделяла визиты сама. Теперь их рассчитывают в
|
||
DDS, а повторять зерно сессий ради представления с переименованными
|
||
колонками незачем. Здесь вы учитесь дневной агрегации, поэтому зерно — день
|
||
и устройство. Выбор описан в разделе «Форма: по зерну, не по цене запроса»
|
||
[справочника DM](../architecture/dm.md).
|
||
|
||
## Что сделать
|
||
|
||
Источник — `dds.session_v`. Зерно — **день сессии × категория устройства**.
|
||
Зерно новое, поэтому витрина хранится готовым агрегатом — см. [«Как принято
|
||
на ступени 1»](README.md#как-принято-на-ступени-1). Создайте пять объектов:
|
||
`dm.session_overview_rep` / `_dist`, донор `_stage_rep` / `_stage_dist` и
|
||
публичное представление `dm.session_overview_v`. Ключ партиции — день.
|
||
|
||
### Состав колонок
|
||
|
||
| Колонка | Тип | Значение |
|
||
|---|---|---|
|
||
| `report_date` | `Date` | День сессии |
|
||
| `device_category` | `LowCardinality(String)` | Категория устройства |
|
||
| `sessions` | `UInt64` | Число визитов |
|
||
| `visitors` | `UInt64` | Число разных `client_id` |
|
||
| `bounce_sessions` | `UInt64` | Визиты ровно из одного события |
|
||
| `purchase_sessions` | `UInt64` | Визиты хотя бы с одной покупкой |
|
||
| `duration_seconds_total` | `UInt64` | Суммарная длительность визитов |
|
||
| `events_total` | `UInt64` | Число событий во всех визитах |
|
||
| `pageviews` | `UInt64` | Число просмотров страниц |
|
||
| `cart_adds` | `UInt64` | Число добавлений в корзину |
|
||
| `purchases` | `UInt64` | Число покупок |
|
||
| `_load_id` | `String` | Идентификатор запуска, собравшего день |
|
||
| `_load_ts` | `DateTime64(3, 'UTC')` | Время сборки |
|
||
|
||
Возьмите `device_category` из сессии: DDS уже заменил код словом. Из четырех
|
||
категорий встречаются `desktop`, `mobile` и `tablet`. Строку для `tv`
|
||
создавайте только при появлении таких визитов.
|
||
|
||
Вместо `avg_duration_seconds` храните слагаемые. Среднее из средних по трем
|
||
устройствам даст неверный ответ за день: число сессий в категориях
|
||
различается, поэтому средние нужно взвешивать. Потребитель делит сумму
|
||
`duration_seconds_total` на сумму `sessions`. Долю отказов считают так же:
|
||
сумму `bounce_sessions` делят на сумму `sessions`, а не усредняют готовые
|
||
доли.
|
||
|
||
### Ритм пересборки
|
||
|
||
Сессии прожитого дня больше не меняются. Как в задании 2, определяйте
|
||
диапазон от первого несобранного прожитого дня до последнего прожитого.
|
||
Соберите его в донор и замените дневные партиции. Добавьте задачу в
|
||
`dm_transform`.
|
||
|
||
### Ключ шардирования
|
||
|
||
Выберите ключ самостоятельно. Визитов с планшета мало, с телефонов и
|
||
компьютеров — значительно больше. Если хотите взять хеш только от
|
||
`device_category`, сначала посчитайте строки на каждом шарде. Затем
|
||
объясните, почему такое распределение вас устраивает.
|
||
|
||
Ключ донора — тот же, что у цели (см. [«Как принято на ступени
|
||
1»](README.md#как-принято-на-ступени-1) и раздел «Раскладка по шардам»
|
||
[справочника хранилища](../architecture/storage.md)).
|
||
|
||
## Почему сумма `visitors` сходится с `dm.daily_traffic_v`
|
||
|
||
Сравните сумму `visitors` по устройствам за день с `dm.daily_traffic_v`. На
|
||
стенде значения совпадут: устройство приписано куке на всю жизнь, поэтому за
|
||
день она учитывается только в одной строке. Это свойство мира стенда; см.
|
||
раздел «Паспорт куки» в [словаре понятий](../../CONTEXT.md).
|
||
|
||
Если появятся визиты одной куки с двух устройств, сумма начнет завышать
|
||
аудиторию. Проверки счетчиков по категориям этого не обнаружат. Число
|
||
посетителей дня берите из `dm.daily_traffic_v`, где оно рассчитано для дня
|
||
целиком.
|
||
|
||
## Типичная ошибка
|
||
|
||
Повторное выделение визитов из событий может дать другие границы сессий, чем
|
||
в DDS. Используйте готовые сессии из `dds.session_v`. Если общее число
|
||
событий совпало с источником, а число сессий завышено, вероятная причина —
|
||
сборка витрины из событий вместо сессий.
|
||
|
||
## Как проверить себя
|
||
|
||
Деловой ключ — `device_category` внутри дня. Получите прямой агрегат из
|
||
`dds.session_v` за день. Соедините его с `dm.session_overview_v` полным
|
||
внешним соединением по ключу. Посчитайте строки, где ключ отсутствует с
|
||
одной из сторон или различается любой счетчик. Расхождений должно быть ноль.
|
||
|
||
Еще две проверки дневных итогов:
|
||
|
||
- сумма `sessions` равна числу строк `dds.session_v` за день — без потерь и
|
||
повторного учета визитов;
|
||
- сумма `events_total` равна сумме `events_total` по сессиям того же дня.
|
||
|
||
## Приемка
|
||
|
||
- [ ] созданы пять объектов, донор объявлен через `AS` и шардируется ключом
|
||
цели;
|
||
- [ ] в `dm.session_overview_v` колонки перечислены явно;
|
||
- [ ] источник — `dds.session_v`, повторного выделения визитов нет;
|
||
- [ ] физическая таблица не хранит средние и доли;
|
||
- [ ] задача `session_overview` в `homework_check` завершилась успешно;
|
||
- [ ] задача витрины добавлена в `dm_transform`.
|