# Задание 2: `dm.top_pages_daily` **Чему учит:** создавать витрину с новым зерном: пять объектов, донор и замена дневных партиций. Включать ее пересборку в `dm_transform`. ## Сначала прочитать - [«Хранилище и его слои»](../handbook/storage-layers.md); - [«Потоки Airflow и даги модельного времени»](../handbook/airflow-dags.md). ## Роль витрины По дневным показателям страниц аналитик сравнивает просмотры, посетителей и действия с товарами. Добавление в корзину происходит на карточке товара, покупка — на странице подтверждения заказа. Отношение добавлений к просмотрам карточки показывает ее конверсию. Для воронки «просмотр → корзина → покупка» этих данных недостаточно: действия происходят на разных страницах, а связи между ними в агрегате нет. Путь человека исследуют по событиям или сессиям. ## Что сделать Источник — `dds.event_v`. Зерно витрины — **день события × страница**. Читайте DDS напрямую: так выполнение задания не зависит от витрины задания 1. На стенде витрину с новым зерном хранят как готовый агрегат, чтобы не рассчитывать ее заново для каждого запроса. Причины описаны в разделе [«Как принято на ступени 1»](README.md#как-принято-на-ступени-1). Создайте пять объектов: `dm.top_pages_daily_rep` / `_dist`, донор `_stage_rep` / `_stage_dist` и публичное представление `dm.top_pages_daily_v`. Ключ партиции — день, он же единица пересборки. ### Состав колонок | Колонка | Тип | Значение | |---|---|---| | `report_date` | `Date` | День события | | `page_path` | `LowCardinality(String)` | Путь страницы | | `pageviews` | `UInt64` | Число событий `pageview` на странице | | `visitors` | `UInt64` | Число разных `client_id` на странице | | `cart_adds` | `UInt64` | Число событий `add_to_cart` на странице | | `purchases` | `UInt64` | Число событий `purchase` на странице | | `_load_id` | `String` | Идентификатор запуска, собравшего день | | `_load_ts` | `DateTime64(3, 'UTC')` | Время сборки | Вычислите `page_path` из `url`, убрав домен и параметры запроса. Полный адрес разделил бы показатели одной страницы на сотни строк. Учитывайте все три типа событий, а их счетчики вычисляйте через `countIf`. ### Ритм пересборки События прожитого дня больше не меняются. Определяйте объем прогона по состоянию витрины: от первого несобранного прожитого дня до последнего прожитого. Отсчет от последнего собранного дня оставит пропуски после частичного сбоя. Как у `revenue_daily`, заполните донор за весь диапазон одной вставкой, затем замените дневные партиции по одной. ### Ключ шардирования Выберите ключ самостоятельно. У `revenue_daily` кроме дня одно измерение с шестью близкими по объему значениями. Здесь страниц много, и число событий на них сильно различается. У цели и донора используйте одинаковый ключ: иначе при замене партиции строка потеряется на одном шарде и удвоится на другом. О том, [как устроен донор](../architecture/storage.md), читайте в разделе «Раскладка по шардам». ## Типичная ошибка Из-за имени витрины хочется отобрать только просмотры. Но фильтр источника по `event_type = 'pageview'` обнулит `cart_adds` и `purchases`, а запрос не завершится ошибкой. Конверсия карточек станет нулевой. Проверка одной суммы `pageviews` не обнаружит этот фильтр: все просмотры остались на месте. Ошибку покажет сверка `purchases` или `cart_adds` с источником, если за день были покупки или добавления в корзину. Выбирайте проверку под возможную ошибку. Этот подход описан в [справочнике проверок](../architecture/testing.md). ## Как проверить себя Деловой ключ — `page_path` внутри дня. Получите прямой агрегат из `dds.event_v` за день и соедините его с `dm.top_pages_daily_v` полным внешним соединением по ключу. Посчитайте строки, где ключ отсутствует с одной из сторон или различается любой из четырех счетчиков. Расхождений должно быть ноль. Перед полным сравнением проверьте дневные суммы: - сумма `pageviews` равна числу событий `pageview` в `dds.event_v`; - сумма `purchases` равна числу событий `purchase` в том же источнике. Сумма `visitors` по страницам повторно учитывает посетителя, открывшего несколько страниц. Число посетителей за день берите из `dm.daily_traffic_v`. ## Приемка - [ ] созданы пять объектов, донор объявлен через `AS` и шардируется ключом цели; - [ ] в `dm.top_pages_daily_v` явно перечислены колонки, включая `_load_id` и `_load_ts`; - [ ] объем прогона определяется по состоянию витрины без ручного задания; - [ ] задача `top_pages_daily` в `homework_check` завершилась успешно; - [ ] задача витрины добавлена в `dm_transform`, повторный прогон конвейера не меняет результат.