feat(dm): добавлены витрины выручки и трафика

Зачем:
- Показать два ритма пересборки агрегатов на готовых витринах DM.

Что:
- Добавлены физические модели и публичные договоры revenue_daily и daily_traffic.
- Добавлен dm_transform с оконной заменой выручки и полным пересчетом трафика.
- Отрицательный опыт локального соединения через публичные _v зафиксирован; выбран явный GLOBAL LEFT JOIN.
- Замены партиций сериализованы после подтвержденного OOM при трех одновременных задачах.
- Обновлены архитектурные документы и мастер-спека.

Проверка:
- make lint, make config-test, make smoke, make check-clickhouse, make check-services.
- Чистая сборка world_recreate, dds_transform и dm_transform; меры сверены с прямыми агрегатами.
This commit is contained in:
ddadmin committed 2026-08-26 13:55:26 -04:00
1 parent c9bcacd63b
commit da0477f0f1
12 files changed
+436 -25

No files matched your search

+3
View File
@@ -17,6 +17,9 @@ CREATE DATABASE IF NOT EXISTS ods ON CLUSTER clickstream_cluster;
-- База DDS заводится здесь же по той же причине, что и ODS.
CREATE DATABASE IF NOT EXISTS dds ON CLUSTER clickstream_cluster;
-- База витрин завершает цепочку STG → ODS → DDS → DM.
CREATE DATABASE IF NOT EXISTS dm ON CLUSTER clickstream_cluster;
-- Справочники стоят вне цепочки STG → ODS → DDS → DM: в хранилище их никто не
-- производит, а читают их несколько слоёв — ADR 0012. Порядок слоёв к зоне не
-- применяется, её файл идёт сразу за этим.
+78
View File
@@ -0,0 +1,78 @@
-- DM: физические дневные витрины и донор партиций выручки.
-- Выручка хранится в зерне «день заказа × категория товара». День служит
-- единицей пересборки, поэтому совпадает с ключом партиции.
CREATE TABLE IF NOT EXISTS dm.revenue_daily_rep ON CLUSTER clickstream_cluster
(
report_date Date,
product_category LowCardinality(String),
orders UInt64,
units UInt64,
revenue Decimal(18, 2),
aov Decimal(18, 2),
_load_id String,
_load_ts DateTime64(3, 'UTC')
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/{database}/{table}', '{replica}')
PARTITION BY report_date
ORDER BY (report_date, product_category);
-- Категория — единственное измерение кроме дня. Шесть категорий стартового
-- мира близки по объему, поэтому простой ключ раскладывает строки достаточно
-- ровно и не добавляет в учебный пример составной хеш без читателя.
CREATE TABLE IF NOT EXISTS dm.revenue_daily_dist ON CLUSTER clickstream_cluster
AS dm.revenue_daily_rep
ENGINE = Distributed(
'clickstream_cluster',
'dm',
'revenue_daily_rep',
cityHash64(product_category)
);
-- Донор объявлен через AS и шардируется тем же ключом, что цель. REPLACE
-- PARTITION идет по локальным таблицам, поэтому структура и раскладка донора
-- обязаны совпадать с целью (docs/architecture/storage.md, «Раскладка по
-- шардам»).
CREATE TABLE IF NOT EXISTS dm.revenue_daily_stage_rep ON CLUSTER clickstream_cluster
AS dm.revenue_daily_rep
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/{database}/{table}', '{replica}')
PARTITION BY report_date
ORDER BY (report_date, product_category);
CREATE TABLE IF NOT EXISTS dm.revenue_daily_stage_dist ON CLUSTER clickstream_cluster
AS dm.revenue_daily_stage_rep
ENGINE = Distributed(
'clickstream_cluster',
'dm',
'revenue_daily_stage_rep',
cityHash64(product_category)
);
-- Трафик пересчитывается целиком: новая связь куки с пользователем меняет
-- прошлые дни. Версия запуска позволяет точному представлению скрыть строки
-- прежних пересчетов без TRUNCATE и без партиций.
CREATE TABLE IF NOT EXISTS dm.daily_traffic_rep ON CLUSTER clickstream_cluster
(
report_date Date,
visitors UInt64,
known_users UInt64,
_load_id String,
_load_ts DateTime64(3, 'UTC')
)
ENGINE = ReplicatedReplacingMergeTree(
'/clickhouse/tables/{shard}/{database}/{table}',
'{replica}',
_load_ts
)
ORDER BY report_date;
-- Все версии одного дня должны попадать на один шард, иначе FINAL не сможет
-- выбрать последнюю через границу шардов.
CREATE TABLE IF NOT EXISTS dm.daily_traffic_dist ON CLUSTER clickstream_cluster
AS dm.daily_traffic_rep
ENGINE = Distributed(
'clickstream_cluster',
'dm',
'daily_traffic_rep',
cityHash64(report_date)
);
+28
View File
@@ -0,0 +1,28 @@
-- DM: публичные договоры стендовых витрин.
-- День и категория — зерно выручки. Служебные колонки показывают запуск,
-- который последним заменил дневную партицию.
CREATE VIEW IF NOT EXISTS dm.revenue_daily_v ON CLUSTER clickstream_cluster
AS
SELECT
report_date,
product_category,
orders,
units,
revenue,
aov,
_load_id,
_load_ts
FROM dm.revenue_daily_dist;
-- Полный пересчет пишет новую версию каждого дня. FINAL оставляет текущие
-- счетчики и прячет повторы запусков от потребителя.
CREATE VIEW IF NOT EXISTS dm.daily_traffic_v ON CLUSTER clickstream_cluster
AS
SELECT
report_date,
visitors,
known_users,
_load_id,
_load_ts
FROM dm.daily_traffic_dist FINAL;