Files
clickstream-data-platform/docs/labs/optional/incremental-daily-traffic.md
T
ddadmin d6b172e511 docs(labs): уточнены формулировки и шаги работы со связями
Зачем: сделать действия в двух лабораторных понятными студенту без
дополнительной расшифровки названий и временных обозначений.

Что: переименована первая работа, абстрактные заголовки заменены
конкретными действиями. Уточнены выбор копии списка связей и обновление
даты из журнала перед повтором загрузки. Выводы требуют сравнения данных.

Проверка: последовательное чтение глазами студента и независимая проверка
по исходникам; 81 локальная ссылка, неизменность SQL-блоков, diff --check.
2026-09-22 06:15:04 -04:00

11 KiB
Raw Blame History

Как обновлять витрину без полной пересборки

Чему учит: выбирать дни для пересчета по новым данным, проверять результат и повторять незавершенную загрузку.

Факультатив повышенной сложности продолжает работу «Как новые заказы меняют отчет о посетителях». Понадобятся ее запрос сохранения списка связей и таблица default.lab_identity_history. Работайте под student через то же подключение DBeaver.

Стенд пересчитывает dm.daily_traffic_v целиком: новая связь может изменить число известных пользователей в старом дне. Вы построите рядом свою витрину, которая пересчитывает только затронутые дни и дает тот же результат.

При обычном продвижении модельного времени появляются новые дни сессий и новые связи. Уже найденные пары сохраняются, а сессии прежних дней не меняются. Удаление данных, исправления старых сессий и пересоздание мира потребовали бы другого способа обнаружения изменений.

Создайте витрину и журнал успешных загрузок

Создайте две локальные таблицы. Если имена заняты, выберите свои.

CREATE TABLE default.lab_daily_traffic
(
    report_date Date,
    visitors UInt64,
    known_users UInt64,
    observation_day Date
)
ENGINE = ReplacingMergeTree(observation_day)
ORDER BY report_date;

CREATE TABLE default.lab_traffic_runs
(
    observation_day Date
)
ENGINE = MergeTree
ORDER BY observation_day;

В витрине одна актуальная строка на день. Для обновления вставляйте полный новый результат дня с новой observation_day. Читайте витрину с FINAL: для каждого report_date останется строка с максимальной observation_day. Старые версии могут исчезнуть при слиянии, поэтому для воспроизведения прежнего расчета нужна сохраненная история связей.

В журнал записывайте observation_day списка связей, использованного для расчета. Добавляйте дату только после записи всех выбранных дней и успешной сверки. Максимальная дата в журнале укажет, какой список использовался в последней завершенной загрузке.

Выполните первую загрузку целиком

Убедитесь, что world_live стоит на паузе и нет активных прогонов генерации и обработки. Запустите etl_pipeline и дождитесь успеха. Получите текущую observation_day способом из первой работы. Если списка за эту дату еще нет в вашей истории, сохраните его. Повторно вставлять уже сохраненный список не требуется.

Напишите INSERT INTO ... SELECT, который рассчитывает все даты сессий из dds.session_v со списком связей на текущую дату. Правила результата:

Колонка Что считать
report_date session_date
visitors число разных client_id
known_users число разных известных user_id
observation_day дата выбранной копии списка связей

Сессии без известного пользователя сохраняйте в расчете. Несколько кук одного пользователя не должны увеличивать known_users. Для соединения с вашей таблицей связей используйте GLOBAL LEFT JOIN, отобрав одну observation_day.

Построчно сверьте свои report_date, visitors, known_users с dm.daily_traffic_v. Сверка должна находить лишние и отсутствующие даты и различия обоих показателей. Учебную витрину читайте с FINAL. После совпадения запишите дату наблюдения в журнал один раз.

Найдите дни, которые нужно пересчитать

Продвиньте мир на один день: world_next_day с days = 1, затем etl_pipeline; после каждого запуска дождитесь успеха. Сохраните новый список связей запросом из первой работы.

Обозначим максимальную observation_day в журнале P, а дату нового списка связей — H. До записи результата составьте запрос, возвращающий даты для пересчета без повторов. Он должен учесть два изменения:

  • в сессиях появились дни, которых еще нет в вашей витрине;
  • в списке на H появились пары, которых не было в списке на P; у этих кук есть сессии, в том числе за прежние дни.

Сначала выведите даты и выберите один прежний день: какая новая пара потребовала его пересчета и какие сессии с ней связаны? Рядом посчитайте, сколько дат пересчитала бы полная загрузка. Зафиксируйте оба числа; равенство тоже возможно, если новые связи затронули всю историю.

Для сравнения выберите из списка на H пары, у которых день покупки по first_purchase_at позже P. Совпадет ли результат с новыми парами, найденными сравнением списков? Покажите пару, которую ограничение по дате покупки пропускает.

Обновите выбранные дни

Напишите второй INSERT INTO ... SELECT. Для выбранных дат он должен рассчитать все сессии с полным списком связей на H. Прибавление числа новых связей к прежнему known_users не заменяет пересчет разных пользователей.

Вставьте результаты с версией H. Полностью сверьте актуальную учебную витрину со стендовой, включая дни, которые не пересчитывали. Только после совпадения добавьте H в журнал.

Без продвижения мира снова определите P по журналу и повторите выбор дат. Запрос должен вернуть пустой результат, а витрина — остаться прежней. Повторно записывать H в журнал не требуется.

Проверьте повторный запуск после частичной загрузки

Снова запустите world_next_day с days = 1, затем etl_pipeline, дожидаясь успеха каждого. Сохраните новый список связей с его датой H. Получите даты для пересчета, но запишите результат только за одну из них. Остальные пока не загружайте и дату в журнал не добавляйте. Так вы воспроизведете остановку между записями дней, не ломая стенд.

Снова определите P по журналу, выполните запрос выбора дат и пересчет этих дней. Проверьте, что результат совпал со стендовой витриной без очистки уже записанных строк. После сверки запишите H в журнал.

Объясните на этом опыте, почему сохранение нового списка связей еще не означает, что витрина обновлена. Что изменится, если записать H в журнал до обновления витрины?

Что должно получиться

Сохраните SQL первой загрузки, выбора дат, обновления и сверки. После двух новых модельных дней ваша витрина совпадает со стендовой, повтор без новых данных сохраняет результат, а незавершенную загрузку можно продолжить без полной пересборки.

Сравните число пересчитанных дней с полной загрузкой и перечислите, какие дополнительные данные пришлось хранить. Так можно оценить объем работы. На небольшом стенде полный пересчет может быть дешевле. В вашей реализации поиск связей пока читает всю историю покупок — инкрементальным стал именно пересчет дневной витрины.

После работы удалите свои lab_daily_traffic, lab_traffic_runs и lab_identity_history через DROP TABLE, если они больше не нужны.