docs(labs): уточнены формулировки и шаги работы со связями
Зачем: сделать действия в двух лабораторных понятными студенту без дополнительной расшифровки названий и временных обозначений. Что: переименована первая работа, абстрактные заголовки заменены конкретными действиями. Уточнены выбор копии списка связей и обновление даты из журнала перед повтором загрузки. Выводы требуют сравнения данных. Проверка: последовательное чтение глазами студента и независимая проверка по исходникам; 81 локальная ссылка, неизменность SQL-блоков, diff --check.
This commit is contained in:
1 parent
b839a671a1
commit
d6b172e511
4 files changed
+115
-103
No files matched your search
@@ -1,19 +1,21 @@
|
||||
# Когда хранилище узнало пользователя
|
||||
# Как новые заказы меняют отчет о посетителях
|
||||
|
||||
**Чему учит:** различать время события и время появления связи в хранилище,
|
||||
выбирать сведения для обогащения данных на дату расчета.
|
||||
**Чему учит:** сохранять историю связей посетителей с покупателями
|
||||
и использовать ее для воспроизведения прежнего расчета.
|
||||
|
||||
Факультатив доступен после ступени 1. Понадобятся Airflow и DBeaver с
|
||||
подключением `student` по [инструкции](../../../README.md#подключиться-из-dbeaver).
|
||||
Наблюдения сохраняйте в `default` через одно подключение: ваши таблицы
|
||||
локальны узлу. Если предложенное имя занято, выберите свое.
|
||||
Результаты запросов сохраняйте в `default` через одно подключение:
|
||||
ваши таблицы будут доступны только на узле этого подключения.
|
||||
Если предложенное имя таблицы занято, выберите свое.
|
||||
|
||||
На сайте посетителя узнают по куке `client_id`, а магазин знает покупателя
|
||||
по `user_id`. Связь между ними можно установить, когда событие покупки
|
||||
сопоставлено с заказом. Она позволяет обогатить и прежние визиты этой куки.
|
||||
Вы проверите, как новый заказ меняет результат расчета за уже прошедший день.
|
||||
В событиях сайта посетитель обозначен кукой `client_id`, а в заказах
|
||||
покупатель — `user_id`. Сопоставив событие покупки с заказом, можно связать
|
||||
эти идентификаторы. Тогда и к прежним визитам этой куки можно добавить
|
||||
пользователя магазина. Вы проверите, как появление такой связи меняет число
|
||||
известных пользователей в отчете за прошедший день.
|
||||
|
||||
## Соберите связи с подтверждением
|
||||
## Сопоставьте посетителей с покупателями
|
||||
|
||||
Поставьте `world_live` на паузу, дождитесь завершения начатых прогонов
|
||||
генерации и обработки. Запустите `etl_pipeline` и дождитесь успеха.
|
||||
@@ -26,8 +28,9 @@
|
||||
| `dds.event_v` | `event_type`, `event_time`, `client_id`, `purchase_id` |
|
||||
| `dds.order_v` | `order_id`, `user_id` |
|
||||
|
||||
В результате нужна одна строка на пару `client_id`, `user_id` и самое раннее
|
||||
время найденной покупки, подтверждающей эту пару. Назовите его `first_purchase_at`.
|
||||
В результате нужна одна строка на пару `client_id`, `user_id`. Для каждой пары
|
||||
найдите самое раннее время события покупки, которое удалось сопоставить
|
||||
с заказом. Назовите эту колонку `first_purchase_at`.
|
||||
В событии `purchase` массив `purchase_id` содержит один номер заказа.
|
||||
Статус заказа не ограничивайте: отмена покупки не меняет владельца куки.
|
||||
|
||||
@@ -37,9 +40,10 @@
|
||||
|
||||
Проверьте уникальность пар и совпадение их полного набора с
|
||||
`dds.identity_map_v`: одного равенства количества недостаточно.
|
||||
Для одной пары покажите номера заказов и события, по которым нашли время.
|
||||
Для одной пары покажите номера заказов и события, по которым получили
|
||||
`first_purchase_at`.
|
||||
|
||||
## Сохраните три наблюдения
|
||||
## Сохраните список связей после каждого модельного дня
|
||||
|
||||
Создайте таблицу:
|
||||
|
||||
@@ -55,16 +59,19 @@ ENGINE = MergeTree
|
||||
ORDER BY (observation_day, client_id, user_id);
|
||||
```
|
||||
|
||||
Для метки наблюдения используйте последний обработанный день событий:
|
||||
Каждая копия списка должна содержать все найденные пары. В колонку
|
||||
`observation_day` запишите последний обработанный день событий:
|
||||
|
||||
```sql
|
||||
SELECT max(event_date) AS observation_day FROM dds.event_v;
|
||||
```
|
||||
|
||||
Обозначим начальную дату **H0**. Это модельная дата, а не календарный день
|
||||
запуска Airflow. После успешного `etl_pipeline` сохраните полный результат
|
||||
своего запроса через `INSERT INTO ... SELECT`, добавив эту дату.
|
||||
Проверьте число строк и уникальность пар за H0.
|
||||
Обозначим полученную дату **H0**. Она показывает, после обработки какого
|
||||
модельного дня сохранен список; календарная дата запуска Airflow здесь
|
||||
не используется. Сохраните полный результат своего запроса через
|
||||
`INSERT INTO ... SELECT`, добавив H0 в `observation_day` каждой строки.
|
||||
Сверьте число записанных строк с результатом исходного запроса и проверьте
|
||||
уникальность пар для этой даты.
|
||||
|
||||
Затем дважды выполните последовательность:
|
||||
|
||||
@@ -72,62 +79,63 @@ SELECT max(event_date) AS observation_day FROM dds.event_v;
|
||||
2. Запустите `etl_pipeline` и дождитесь успеха.
|
||||
3. Получите новую `observation_day`, сохраните полный набор связей и проверьте его.
|
||||
|
||||
Получатся наблюдения **H0**, **H1** и **H2**. Каждую дату записывайте один раз:
|
||||
обычный `MergeTree` не устраняет повторы вставки. Между этими действиями
|
||||
не запускайте генерацию отдельно от наблюдения.
|
||||
Получатся три копии списка: после дней **H0**, **H1** и **H2**.
|
||||
Для каждой даты сохраняйте список один раз: обычный `MergeTree`
|
||||
не устраняет повторы вставки. Сохраните и проверьте список перед тем,
|
||||
как запускать следующий модельный день.
|
||||
|
||||
## Сопоставьте два времени
|
||||
## Сравните дату покупки с датой появления связи
|
||||
|
||||
Сравните наборы пар в соседних наблюдениях. Для нескольких новых связей
|
||||
покажите `client_id`, `user_id`, `first_purchase_at` и первую дату наблюдения,
|
||||
в которой пара появилась. Найдите связь, покупка которой произошла до дня
|
||||
ее обнаружения.
|
||||
Сравните списки за соседние даты: H0 с H1, затем H1 с H2. Найдите пары,
|
||||
которых не было в прежнем списке. Для нескольких таких пар покажите
|
||||
`client_id`, `user_id`, `first_purchase_at` и первую `observation_day`,
|
||||
в которой пара появилась. Найдите пример, где покупка произошла раньше
|
||||
этой даты.
|
||||
|
||||
Для одной такой связи вернитесь к заказу и событию. По данным и
|
||||
[порядку доставки заказов](../../architecture/orders/ingestion.md) объясните,
|
||||
почему связь отсутствовала в прежнем наблюдении. Был ли момент покупки
|
||||
достаточным основанием считать ее уже известной хранилищу?
|
||||
почему пары не было в прежнем списке. Какие данные понадобились для ее
|
||||
появления и когда они стали доступны?
|
||||
|
||||
У пары, которая присутствовала уже в H0, тоже получится минимальная дата
|
||||
наблюдения. В этом случае она означает «пара была известна к началу опыта»:
|
||||
истории до H0 у вас нет. Для новых пар ежедневные наблюдения устанавливают
|
||||
интервал появления связи, а не точное время внутри него.
|
||||
Для пары, которая присутствовала уже в H0, нельзя определить дату появления:
|
||||
у вас нет более ранних копий списка. Для новой пары можно установить
|
||||
интервал между двумя сохранениями, но не точное время внутри него.
|
||||
|
||||
## Пересчитайте прежние визиты
|
||||
## Пересчитайте отчет за прежние дни
|
||||
|
||||
Возьмите один и тот же набор сессий из `dds.session_v` за даты до H0
|
||||
включительно. Постройте два дневных расчета:
|
||||
|
||||
- со связями, сохраненными в H0;
|
||||
- со связями, сохраненными в H2.
|
||||
- со списком связей на H0;
|
||||
- со списком связей на H2.
|
||||
|
||||
Для каждого дня посчитайте посетителей по разным `client_id` и известных
|
||||
пользователей по разным `user_id`. Сессии без связи должны остаться в расчете,
|
||||
но неизвестный пользователь не должен увеличивать число известных.
|
||||
В соединении распределенных сессий с локальной историей используйте
|
||||
`GLOBAL LEFT JOIN` и заранее отберите в истории одну дату наблюдения.
|
||||
В соединении сессий с вашей таблицей используйте `GLOBAL LEFT JOIN`.
|
||||
В таблице связей заранее отберите одну `observation_day`, чтобы копии
|
||||
списка за разные дни не смешались.
|
||||
|
||||
Найдите день с разным числом известных пользователей. Проследите изменение
|
||||
до конкретных связей и прежних сессий. Проверьте, что число посетителей
|
||||
не изменилось и известные пользователи не превышают его.
|
||||
не изменилось, а число известных пользователей не больше числа посетителей.
|
||||
|
||||
Напишите, какой вариант нужен для двух требований к витрине:
|
||||
|
||||
- «пересчитать прошлые визиты с учетом всех сведений, доступных сейчас»;
|
||||
- «воспроизвести расчет, сделанный при наблюдении H0».
|
||||
|
||||
Для второго требования проверьте еще один способ: взять текущие связи,
|
||||
оставив только `first_purchase_at` до конца H0. Совпадет ли полный набор
|
||||
пар с сохраненным в H0? Найденным расхождением обоснуйте выбор истории
|
||||
для воспроизводимого расчета.
|
||||
Теперь проверьте, можно ли воспроизвести расчет на H0 без сохраненного
|
||||
списка за эту дату. Возьмите список на H2 и оставьте только пары,
|
||||
у которых `first_purchase_at` приходится на H0 или более ранний день.
|
||||
Сравните полный набор пар с копией на H0. Выведите пары, которые есть
|
||||
только в одном из списков.
|
||||
На примере найденных различий объясните, какие данные нужно сохранять,
|
||||
чтобы повторить прежний расчет.
|
||||
|
||||
## Что должно получиться
|
||||
|
||||
У вас есть запрос связей с подтверждающими покупками, три сохраненных
|
||||
наблюдения и сравнение двух расчетов на одном наборе сессий. Вы можете
|
||||
показать, когда новая связь стала видна в наблюдениях, и объяснить,
|
||||
какие данные понадобятся для воспроизведения прежнего расчета.
|
||||
У вас есть запрос сопоставления посетителей с покупателями, три сохраненных
|
||||
списка связей и сравнение двух расчетов на одном наборе сессий. На конкретных
|
||||
парах вы можете показать разницу между датой покупки и датой появления пары
|
||||
в сохраненном списке, а также объяснить, что нужно для повторения прежнего
|
||||
расчета.
|
||||
|
||||
Сохраните SQL и таблицу наблюдений: они нужны в продолжении
|
||||
Сохраните SQL и таблицу `lab_identity_history`: они нужны в продолжении
|
||||
[«Как обновлять витрину без полной пересборки»](incremental-daily-traffic.md).
|
||||
Если продолжать не планируете, удалите свою таблицу через `DROP TABLE`.
|
||||
Reference in new issue
Block a user