Зачем: дать практику учета новых связей пользователей при обновлении прежних дней витрины. Что: добавлены две связанные лабораторные с наблюдениями через Airflow, собственными таблицами student и повтором частично записанной загрузки. Обновлены программа, индекс и ссылки из справочников DDS и DM. Проверка: DDL и SQL под student на ClickHouse 26.3.17.56, четыре модельных дня через Airflow, полные сверки и повтор незавершенной загрузки; config-test, lint, локальные ссылки и независимое ревью.
134 lines
9.1 KiB
Markdown
134 lines
9.1 KiB
Markdown
# Когда хранилище узнало пользователя
|
||
|
||
**Чему учит:** различать время события и время появления связи в хранилище,
|
||
выбирать сведения для обогащения данных на дату расчета.
|
||
|
||
Факультатив доступен после ступени 1. Понадобятся Airflow и DBeaver с
|
||
подключением `student` по [инструкции](../../../README.md#подключиться-из-dbeaver).
|
||
Наблюдения сохраняйте в `default` через одно подключение: ваши таблицы
|
||
локальны узлу. Если предложенное имя занято, выберите свое.
|
||
|
||
На сайте посетителя узнают по куке `client_id`, а магазин знает покупателя
|
||
по `user_id`. Связь между ними можно установить, когда событие покупки
|
||
сопоставлено с заказом. Она позволяет обогатить и прежние визиты этой куки.
|
||
Вы проверите, как новый заказ меняет результат расчета за уже прошедший день.
|
||
|
||
## Соберите связи с подтверждением
|
||
|
||
Поставьте `world_live` на паузу, дождитесь завершения начатых прогонов
|
||
генерации и обработки. Запустите `etl_pipeline` и дождитесь успеха.
|
||
На время работы мир будете продвигать вручную; новые дни останутся в стенде.
|
||
|
||
Напишите запрос по двум источникам:
|
||
|
||
| Источник | Нужные поля |
|
||
|---|---|
|
||
| `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`.
|
||
В событии `purchase` массив `purchase_id` содержит один номер заказа.
|
||
Статус заказа не ограничивайте: отмена покупки не меняет владельца куки.
|
||
|
||
Источники распределены по разным ключам. Для соединения используйте
|
||
`GLOBAL INNER JOIN`, заключив выборки событий и заказов в подзапросы.
|
||
Устройство источников описано в [карте идентичностей](../../architecture/dds/identity.md).
|
||
|
||
Проверьте уникальность пар и совпадение их полного набора с
|
||
`dds.identity_map_v`: одного равенства количества недостаточно.
|
||
Для одной пары покажите номера заказов и события, по которым нашли время.
|
||
|
||
## Сохраните три наблюдения
|
||
|
||
Создайте таблицу:
|
||
|
||
```sql
|
||
CREATE TABLE default.lab_identity_history
|
||
(
|
||
observation_day Date,
|
||
client_id UInt64,
|
||
user_id UInt64,
|
||
first_purchase_at DateTime('Europe/Samara')
|
||
)
|
||
ENGINE = MergeTree
|
||
ORDER BY (observation_day, client_id, user_id);
|
||
```
|
||
|
||
Для метки наблюдения используйте последний обработанный день событий:
|
||
|
||
```sql
|
||
SELECT max(event_date) AS observation_day FROM dds.event_v;
|
||
```
|
||
|
||
Обозначим начальную дату **H0**. Это модельная дата, а не календарный день
|
||
запуска Airflow. После успешного `etl_pipeline` сохраните полный результат
|
||
своего запроса через `INSERT INTO ... SELECT`, добавив эту дату.
|
||
Проверьте число строк и уникальность пар за H0.
|
||
|
||
Затем дважды выполните последовательность:
|
||
|
||
1. Запустите `world_next_day` с `days = 1` и дождитесь успеха.
|
||
2. Запустите `etl_pipeline` и дождитесь успеха.
|
||
3. Получите новую `observation_day`, сохраните полный набор связей и проверьте его.
|
||
|
||
Получатся наблюдения **H0**, **H1** и **H2**. Каждую дату записывайте один раз:
|
||
обычный `MergeTree` не устраняет повторы вставки. Между этими действиями
|
||
не запускайте генерацию отдельно от наблюдения.
|
||
|
||
## Сопоставьте два времени
|
||
|
||
Сравните наборы пар в соседних наблюдениях. Для нескольких новых связей
|
||
покажите `client_id`, `user_id`, `first_purchase_at` и первую дату наблюдения,
|
||
в которой пара появилась. Найдите связь, покупка которой произошла до дня
|
||
ее обнаружения.
|
||
|
||
Для одной такой связи вернитесь к заказу и событию. По данным и
|
||
[порядку доставки заказов](../../architecture/orders/ingestion.md) объясните,
|
||
почему связь отсутствовала в прежнем наблюдении. Был ли момент покупки
|
||
достаточным основанием считать ее уже известной хранилищу?
|
||
|
||
У пары, которая присутствовала уже в H0, тоже получится минимальная дата
|
||
наблюдения. В этом случае она означает «пара была известна к началу опыта»:
|
||
истории до H0 у вас нет. Для новых пар ежедневные наблюдения устанавливают
|
||
интервал появления связи, а не точное время внутри него.
|
||
|
||
## Пересчитайте прежние визиты
|
||
|
||
Возьмите один и тот же набор сессий из `dds.session_v` за даты до H0
|
||
включительно. Постройте два дневных расчета:
|
||
|
||
- со связями, сохраненными в H0;
|
||
- со связями, сохраненными в H2.
|
||
|
||
Для каждого дня посчитайте посетителей по разным `client_id` и известных
|
||
пользователей по разным `user_id`. Сессии без связи должны остаться в расчете,
|
||
но неизвестный пользователь не должен увеличивать число известных.
|
||
В соединении распределенных сессий с локальной историей используйте
|
||
`GLOBAL LEFT JOIN` и заранее отберите в истории одну дату наблюдения.
|
||
|
||
Найдите день с разным числом известных пользователей. Проследите изменение
|
||
до конкретных связей и прежних сессий. Проверьте, что число посетителей
|
||
не изменилось и известные пользователи не превышают его.
|
||
|
||
Напишите, какой вариант нужен для двух требований к витрине:
|
||
|
||
- «пересчитать прошлые визиты с учетом всех сведений, доступных сейчас»;
|
||
- «воспроизвести расчет, сделанный при наблюдении H0».
|
||
|
||
Для второго требования проверьте еще один способ: взять текущие связи,
|
||
оставив только `first_purchase_at` до конца H0. Совпадет ли полный набор
|
||
пар с сохраненным в H0? Найденным расхождением обоснуйте выбор истории
|
||
для воспроизводимого расчета.
|
||
|
||
## Что должно получиться
|
||
|
||
У вас есть запрос связей с подтверждающими покупками, три сохраненных
|
||
наблюдения и сравнение двух расчетов на одном наборе сессий. Вы можете
|
||
показать, когда новая связь стала видна в наблюдениях, и объяснить,
|
||
какие данные понадобятся для воспроизведения прежнего расчета.
|
||
|
||
Сохраните SQL и таблицу наблюдений: они нужны в продолжении
|
||
[«Как обновлять витрину без полной пересборки»](incremental-daily-traffic.md).
|
||
Если продолжать не планируете, удалите свою таблицу через `DROP TABLE`.
|