refactor(ods): упрощены имена таблиц заказов

- Зачем:
  - ODS должен показывать сущность заказа, а не способ её доставки слепком.
- Что:
  - физические таблицы и представление переведены на имена `order_*`.
  - SQL загрузки, DAG и документация приведены к тому же словарю.
- Проверка:
  - `make config-test`, `make lint`.
  - `make clean && make up`, `make smoke`, `make check-clickhouse`, `make check-services`.
This commit is contained in:
ddadmin committed 2026-08-21 10:49:02 +03:00
1 parent a24dfc4510
commit 2a94ee9bde
13 files changed
+48 -49

No files matched your search

+2 -2
View File
@@ -101,8 +101,8 @@ def orders_ingest():
logging.info("срез разобран: _load_id %s", load_id) logging.info("срез разобран: _load_id %s", load_id)
pull_batch("stg/orders_raw_load.sql") >> parse_batch( pull_batch("stg/orders_raw_load.sql") >> parse_batch(
"ods/order_snapshot_load.sql", "ods/order_load.sql",
"ods/order_snapshot_errors_load.sql", "ods/order_errors_load.sql",
) )
+1 -1
View File
@@ -9,7 +9,7 @@
команде Airflow, но порция чтения больше не считается полным слепком и не команде Airflow, но порция чтения больше не считается полным слепком и не
публикуется заменой партиции `snapshot_date`. Прочитанные строки получают публикуется заменой партиции `snapshot_date`. Прочитанные строки получают
`_load_id` запуска, разбираются из одного среза STG в годные строки и ошибки, `_load_id` запуска, разбираются из одного среза STG в годные строки и ошибки,
а `ods.order_snapshot` хранит принятые версии заказа в а `ods.order` хранит принятые версии заказа в
`ReplacingMergeTree(updated_at)`. Ключ сущности — `order_id`, партиция строится `ReplacingMergeTree(updated_at)`. Ключ сущности — `order_id`, партиция строится
от неизменного `created_at`, все версии ключа направляются на один шард. от неизменного `created_at`, все версии ключа направляются на один шард.
+1 -1
View File
@@ -37,7 +37,7 @@
`person_id` заказ показывает как `user_id`, кликстрим остаётся анонимным — `person_id` заказ показывает как `user_id`, кликстрим остаётся анонимным —
[мост к склейке](identity.md). [мост к склейке](identity.md).
- **Приём — пакетный забор**: одно прямое чтение Kafka в STG, два - **Приём — пакетный забор**: одно прямое чтение Kafka в STG, два
`INSERT SELECT` в типизированный ODS и таблицу ошибок; `ods.order_snapshot` `INSERT SELECT` в типизированный ODS и таблицу ошибок; `ods.order`
принимает версии заказа на `ReplacingMergeTree(updated_at)` — принимает версии заказа на `ReplacingMergeTree(updated_at)` —
[приём из Kafka в ODS](ingestion.md). [приём из Kafka в ODS](ingestion.md).
- **Стартовый мир отправляет семь слепков** (дни 0…6): у последнего прожитого - **Стартовый мир отправляет семь слепков** (дни 0…6): у последнего прожитого
+1 -1
View File
@@ -61,7 +61,7 @@
**Что из двух дорог видно.** В `dds.order` дороги неразличимы — там последняя **Что из двух дорог видно.** В `dds.order` дороги неразличимы — там последняя
версия; различает их история версий: сырьё STG и физические версии версия; различает их история версий: сырьё STG и физические версии
`ods.order_snapshot` до фоновых слияний, а в витринах — выручка дня, которая `ods.order` до фоновых слияний, а в витринах — выручка дня, которая
сначала выросла, потом убыла. Полное различение не обещано: слепок — состояние сначала выросла, потом убыла. Полное различение не обещано: слепок — состояние
на границе суток, и оплата с отменой в один день в сырье неразличимы; то же у на границе суток, и оплата с отменой в один день в сырье неразличимы; то же у
сильно опоздавших, приехавших уже терминальными. Точную форму этого урока сильно опоздавших, приехавших уже терминальными. Точную форму этого урока
+9 -9
View File
@@ -43,12 +43,12 @@
Один следующий `task_id` отвечает за весь переход STG → ODS. Внутри него два Один следующий `task_id` отвечает за весь переход STG → ODS. Внутри него два
последовательных `INSERT SELECT` читают неизменный срез по `_load_id`: первый последовательных `INSERT SELECT` читают неизменный срез по `_load_id`: первый
пишет годные строки в `ods.order_snapshot`, второй — брак в пишет годные строки в `ods.order`, второй — брак в `ods.order_errors`.
`ods.order_snapshot_errors`. Транзакции между запросами нет. При частичном сбое Транзакции между запросами нет. При частичном сбое Airflow повторяет весь
Airflow повторяет весь `task_id`; одинаковые исходные строки и служебные метки `task_id`; одинаковые исходные строки и служебные метки не вычисляются заново.
не вычисляются заново. Запросы лежат рядом с целями: Запросы лежат рядом с целями:
[`order_snapshot_load.sql`](../../../sql/ods/order_snapshot_load.sql) и [`order_load.sql`](../../../sql/ods/order_load.sql) и
[`order_snapshot_errors_load.sql`](../../../sql/ods/order_snapshot_errors_load.sql). [`order_errors_load.sql`](../../../sql/ods/order_errors_load.sql).
Условия запросов взаимодополняющие: один общий предикат определяет брак, а Условия запросов взаимодополняющие: один общий предикат определяет брак, а
годная ветвь использует его буквальное отрицание. Все функции предиката годная ветвь использует его буквальное отрицание. Все функции предиката
@@ -90,9 +90,9 @@ JSON-объектом с точным набором ключей: `order_id`, `
## Роль ODS ## Роль ODS
`ods.order_snapshot_rep` хранит физически принятые версии в `ods.order_rep` хранит физически принятые версии в
`ReplacingMergeTree(updated_at)`. Ключ сортировки — `order_id`, партиция — день `ReplacingMergeTree(updated_at)`. Ключ сортировки — `order_id`, партиция — день
неизменного `created_at`. `ods.order_snapshot_dist` шардирует по неизменного `created_at`. `ods.order_dist` шардирует по
`cityHash64(order_id)`: только так все версии заказа попадают на один шард и `cityHash64(order_id)`: только так все версии заказа попадают на один шард и
`FINAL` даёт корректный результат через распределённую таблицу. `FINAL` даёт корректный результат через распределённую таблицу.
@@ -174,7 +174,7 @@ JSON-объектом с точным набором ключей: `order_id`, `
После исправления После исправления
[#102](https://git.dementev.space/ddmitry/clickstream-data-platform/issues/102) [#102](https://git.dementev.space/ddmitry/clickstream-data-platform/issues/102)
честный прогон дня снят на живом стенде 20 августа 2026 года: все 1694 строки честный прогон дня снят на живом стенде 20 августа 2026 года: все 1694 строки
слепка дня 7 приняты, `ods.order_snapshot_errors` осталась пустой. У заказа слепка дня 7 приняты, `ods.order_errors` осталась пустой. У заказа
`20260608-0007`, который прежде приходил с отрицательным итогом, теперь `20260608-0007`, который прежде приходил с отрицательным итогом, теперь
`5490.00 − 823.50 + 299.00 = 4965.50`. `5490.00 − 823.50 + 299.00 = 4965.50`.
+1 -1
View File
@@ -25,6 +25,6 @@
пользователей и число двухкуковых пар растут, пока мир едет, — опоры из них пользователей и число двухкуковых пар растут, пока мир едет, — опоры из них
не выходит; генератор сторожит хеш, транспорт — счёт событий. не выходит; генератор сторожит хеш, транспорт — счёт событий.
- **Опись описывает мир, а не доставку.** Работа генератора кончается на - **Опись описывает мир, а не доставку.** Работа генератора кончается на
Kafka: дошли ли байты до `ods.order_snapshot` — вопрос стенда и его Kafka: дошли ли байты до `ods.order` — вопрос стенда и его
проверок. Поэтому счёта строк у слепка в описи нет; понадобится проверка проверок. Поэтому счёта строк у слепка в описи нет; понадобится проверка
приёма заказов — число заведётся вместе с ней. приёма заказов — число заведётся вместе с ней.
+17 -18
View File
@@ -60,7 +60,7 @@ CSV-файла. Живёт он вне цепочки слоёв, в зоне `d
приходит от транспорта: слой хранит то, что доехало по топику, и зовётся именем приходит от транспорта: слой хранит то, что доехало по топику, и зовётся именем
топика — `hits_raw` от `hits`, `orders_raw` от `orders`. В типизированных слоях топика — `hits_raw` от `hits`, `orders_raw` от `orders`. В типизированных слоях
имя приходит от предметной области и стоит в единственном числе: `event`, имя приходит от предметной области и стоит в единственном числе: `event`,
`order_snapshot`, `session`. Граница между «как привезли» и «что это такое» `order`, `session`. Граница между «как привезли» и «что это такое»
проходит по STG, и имена её показывают. проходит по STG, и имена её показывают.
## Раскладка по шардам ## Раскладка по шардам
@@ -91,7 +91,7 @@ CSV-файла. Живёт он вне цепочки слоёв, в зоне `d
по `cityHash64(order_id)`; ключи остальных частей будущей модели и витрин по `cityHash64(order_id)`; ключи остальных частей будущей модели и витрин
появятся вместе с ними. появятся вместе с ними.
Замена партиций не используется для `ods.order_snapshot`: версии прошлых дней Замена партиций не используется для `ods.order`: версии прошлых дней
доливаются, а прямое чтение Kafka не задаёт границы полного слепка ([ADR доливаются, а прямое чтение Kafka не задаёт границы полного слепка ([ADR
0010](../adr/0010-order-versions-in-ods.md)). Если партиционная пересборка 0010](../adr/0010-order-versions-in-ods.md)). Если партиционная пересборка
понадобится будущим объектам DDS или DM, партиция-донор должна быть заранее понадобится будущим объектам DDS или DM, партиция-донор должна быть заранее
@@ -141,7 +141,7 @@ kafka_offset)`: разбор полётов идёт от «какое сооб
заказов — пакетным шагом. Дальше метка переносится в ODS как есть и отвечает на заказов — пакетным шагом. Дальше метка переносится в ODS как есть и отвечает на
вопрос «когда строка приехала в хранилище», а не «когда её разобрали». В вопрос «когда строка приехала в хранилище», а не «когда её разобрали». В
`ods.event` она же служит колонкой версии `ReplacingMergeTree` и схлопывает `ods.event` она же служит колонкой версии `ReplacingMergeTree` и схлопывает
повтор доставки. У `ods.order_snapshot` версию задаёт `updated_at` источника; повтор доставки. У `ods.order` версию задаёт `updated_at` источника;
`_load_ts` только показывает, когда конкретная строка приехала. `_load_ts` только показывает, когда конкретная строка приехала.
`created_at` и `updated_at` заказа к служебным колонкам хранилища не относятся. `created_at` и `updated_at` заказа к служебным колонкам хранилища не относятся.
@@ -181,9 +181,9 @@ snake_case-имена и расшифровку кодов.
## Версии заказов ## Версии заказов
`ods.order_snapshot_rep` хранит принятые версии в `ods.order_rep` хранит принятые версии в
`ReplacingMergeTree(updated_at)`: ключ сортировки — `order_id`, партиция — `ReplacingMergeTree(updated_at)`: ключ сортировки — `order_id`, партиция —
`toDate(created_at)`. `ods.order_snapshot_dist` шардирует по `toDate(created_at)`. `ods.order_dist` шардирует по
`cityHash64(order_id)`. Все версии заказа лежат в одной партиции, чтобы их могли `cityHash64(order_id)`. Все версии заказа лежат в одной партиции, чтобы их могли
схлопывать фоновые слияния, и на одном шарде, чтобы распределённый `FINAL` схлопывать фоновые слияния, и на одном шарде, чтобы распределённый `FINAL`
выбрал одного победителя. выбрал одного победителя.
@@ -414,7 +414,7 @@ D0 и к реальному календарю не привязана; паке
kafka_offset)`: смотрят такую таблицу от класса, а внутри класса — по координатам kafka_offset)`: смотрят такую таблицу от класса, а внутри класса — по координатам
доставки. доставки.
`ods.order_snapshot_errors` держит тот же диагностический минимум и `_load_id` `ods.order_errors` держит тот же диагностический минимум и `_load_id`
запуска. У заказов три класса по приоритету: `not_an_object`, запуска. У заказов три класса по приоритету: `not_an_object`,
`keyset_mismatch`, `field_invalid`. Сырой текст остаётся рядом, поэтому класс не `keyset_mismatch`, `field_invalid`. Сырой текст остаётся рядом, поэтому класс не
разрастается до имени отдельного поля. Точная граница приёма — в разрастается до имени отдельного поля. Точная граница приёма — в
@@ -534,15 +534,15 @@ Airflow читает и собирает эти файлы штатным шаб
| `ods` | `ods.event_v` | актуальная версия события с полями источника | | `ods` | `ods.event_v` | актуальная версия события с полями источника |
| `ods` | `ods.event_errors_rep` / `_dist` | строки, не прошедшие строгий приём | | `ods` | `ods.event_errors_rep` / `_dist` | строки, не прошедшие строгий приём |
| `ods` | `ods.event_mv`, `ods.event_errors_mv` | разбор сырья в событие и в ошибки | | `ods` | `ods.event_mv`, `ods.event_errors_mv` | разбор сырья в событие и в ошибки |
| `ods` | `ods.order_snapshot_rep` / `_dist` | типизированные версии заказа | | `ods` | `ods.order_rep` / `_dist` | типизированные версии заказа |
| `ods` | `ods.order_v` | текущая версия заказа на языке источника | | `ods` | `ods.order_v` | текущая версия заказа на языке источника |
| `ods` | `ods.order_snapshot_errors_rep` / `_dist` | строки слепка, не прошедшие строгий приём | | `ods` | `ods.order_errors_rep` / `_dist` | строки слепка, не прошедшие строгий приём |
| `dic` | `dic.products_file` | чтец CSV-каталога, общего с генератором | | `dic` | `dic.products_file` | чтец CSV-каталога, общего с генератором |
| `dic` | `dic.products` | словарь товаров поверх подложки | | `dic` | `dic.products` | словарь товаров поверх подложки |
Матвью разбора у заказов нет: срез сырья раскладывают по этим двум целям два Матвью разбора у заказов нет: срез сырья раскладывают по этим двум целям два
`INSERT SELECT` шага `parse_batch` из файлов `sql/ods/order_snapshot_load.sql` `INSERT SELECT` шага `parse_batch` из файлов `sql/ods/order_load.sql` и
и `sql/ods/order_snapshot_errors_load.sql`. `sql/ods/order_errors_load.sql`.
Слой DDS и слой DM появляются на следующих этапах; их состав задан разделом Слой DDS и слой DM появляются на следующих этапах; их состав задан разделом
7 мастер-спеки и переносится сюда по мере постройки. 7 мастер-спеки и переносится сюда по мере постройки.
@@ -606,14 +606,13 @@ DDL-словарь с файловым источником внутри `user_f
`_load_id`, пересечение ветвей — ноль. Все восемь строк брака — версии одного `_load_id`, пересечение ветвей — ноль. Все восемь строк брака — версии одного
заказа с отрицательным `total`; это дефект генератора, разобранный в заказа с отрицательным `total`; это дефект генератора, разобранный в
[спецификации приёма](orders/ingestion.md), «Что проверено». На управляемой [спецификации приёма](orders/ingestion.md), «Что проверено». На управляемой
порции из пяти строк (две версии порции из пяти строк (две версии одного заказа плюс по одной строке каждого
одного заказа плюс по одной строке каждого класса брака) годные ушли в класса брака) годные ушли в `ods.order`, брак — в `ods.order_errors` с
`ods.order_snapshot`, брак — в `ods.order_snapshot_errors` с ожидаемыми ожидаемыми классами. Обе версии легли в одну партицию и на один шард; `FINAL`
классами. Обе версии легли в одну партицию и на один шард; `FINAL` через через распределённую таблицу вернул одну строку — ту, у которой `updated_at`
распределённую таблицу вернул одну строку — ту, у которой `updated_at` позже, — позже, — тогда как физический счёт показывал две. Повтор задачи с тем же
тогда как физический счёт показывал две. Повтор задачи с тем же `_load_id` `_load_id` строку в `ods.order_v` и её `_load_ts` не изменил, а таблица ошибок
строку в `ods.order_v` и её `_load_ts` не изменил, а таблица ошибок записала записала тот же брак второй раз, как и обещано спецификацией приёма.
тот же брак второй раз, как и обещано спецификацией приёма.
Отдельно измерено, что **сводка вставки не годится в счётчики строк**: у Отдельно измерено, что **сводка вставки не годится в счётчики строк**: у
запроса с `WHERE` `read_rows` считает прочитанное с диска, а не подошедшее, — запроса с `WHERE` `read_rows` считает прочитанное с диска, а не подошедшее, —
@@ -64,7 +64,7 @@ Debezium проводит ту же границу внутри одного с
`created_at` и `updated_at` — аудит строки источника. Поэтому `created_at` и `updated_at` — аудит строки источника. Поэтому
`toDate(created_at)` в `toDate(created_at)` в
[спецификации приёма заказов](../architecture/orders/ingestion.md) [спецификации приёма заказов](../architecture/orders/ingestion.md)
используется как стабильный технический ключ партиции `ods.order_snapshot`: используется как стабильный технический ключ партиции `ods.order`:
это день создания строки это день создания строки
источника, а не доказательство дня бизнес-события. источника, а не доказательство дня бизнес-события.
+4 -4
View File
@@ -219,7 +219,7 @@ Ecommerce (заполнены только у торговых событий):
Обоснование и проверка разбора — в Обоснование и проверка разбора — в
[исследовании формата](../research/2026-08-16-order-snapshot-wire-format.md). [исследовании формата](../research/2026-08-16-order-snapshot-wire-format.md).
- `ods.order_snapshot` принимает версии заказа в - `ods.order` принимает версии заказа в
`ReplacingMergeTree(updated_at)`: `ORDER BY order_id`, партиция по дню `ReplacingMergeTree(updated_at)`: `ORDER BY order_id`, партиция по дню
неизменного `created_at`, шардирование по `cityHash64(order_id)`. неизменного `created_at`, шардирование по `cityHash64(order_id)`.
`snapshot_date` остаётся датой наблюдения источника, но не задаёт публикацию `snapshot_date` остаётся датой наблюдения источника, но не задаёт публикацию
@@ -410,7 +410,7 @@ README.
| STG | `stg.hits_raw_kafka`, `stg.hits_raw` + MV | сырые строки событий, Kafka Engine на обеих нодах | | STG | `stg.hits_raw_kafka`, `stg.hits_raw` + MV | сырые строки событий, Kafka Engine на обеих нодах |
| STG | `stg.orders_raw_kafka`, `stg.orders_raw`, без MV | сырые строки слепка; чтец на ноде 1, забирает пакетный шаг | | STG | `stg.orders_raw_kafka`, `stg.orders_raw`, без MV | сырые строки слепка; чтец на ноде 1, забирает пакетный шаг |
| ODS | `ods.event` (+`_errors`), `ods.event_v` | типизированные версии событий, брак и точное актуальное состояние | | ODS | `ods.event` (+`_errors`), `ods.event_v` | типизированные версии событий, брак и точное актуальное состояние |
| ODS | `ods.order_snapshot` (+`_errors`), `ods.order_v` | типизированные версии заказов, брак и точное текущее состояние | | ODS | `ods.order` (+`_errors`), `ods.order_v` | типизированные версии заказов, брак и точное текущее состояние |
| DDS | `dds.session` | сборка сессий из событий (наследник `dds.click`) | | DDS | `dds.session` | сборка сессий из событий (наследник `dds.click`) |
| DDS | `dds.event_v` | представление над `ods.event`: snake_case-имена, расшифровка кодов `DeviceCategory`; витрины DM читают его, а не ODS напрямую | | DDS | `dds.event_v` | представление над `ods.event`: snake_case-имена, расшифровка кодов `DeviceCategory`; витрины DM читают его, а не ODS напрямую |
| DDS | модель заказов | зерно, связи и материализация проектируются на этапе DDS | | DDS | модель заказов | зерно, связи и материализация проектируются на этапе DDS |
@@ -428,7 +428,7 @@ README.
матвью к нему не привязана, и сырьё забирает шаг, которым управляет Airflow — матвью к нему не привязана, и сырьё забирает шаг, которым управляет Airflow —
одно прямое чтение вставляет порцию в `stg.orders_raw` с `_load_id` запуска. одно прямое чтение вставляет порцию в `stg.orders_raw` с `_load_id` запуска.
Один следующий `task_id` двумя последовательными запросами пишет годные строки Один следующий `task_id` двумя последовательными запросами пишет годные строки
и ошибки из того же среза. `ods.order_snapshot` хранит версии по `updated_at`, и ошибки из того же среза. `ods.order` хранит версии по `updated_at`,
а не публикует партицию `snapshot_date`. Слой сырья остаётся точкой повтора и а не публикует партицию `snapshot_date`. Слой сырья остаётся точкой повтора и
разбора одной принятой порции. разбора одной принятой порции.
@@ -436,7 +436,7 @@ README.
из опорных точек раздела 12 переформулировано под них. из опорных точек раздела 12 переформулировано под них.
Состав служебных колонок задаёт дока хранилища. Спеке важны два следствия: Состав служебных колонок задаёт дока хранилища. Спеке важны два следствия:
`ods.event` и `ods.order_snapshot` получают метку загрузки `_load_ts`, но у `ods.event` и `ods.order` получают метку загрузки `_load_ts`, но у
заказа бизнес-версию задаёт `updated_at`; `_load_id` проходит через STG и обе заказа бизнес-версию задаёт `updated_at`; `_load_id` проходит через STG и обе
цели ODS. Таблицы цели ODS. Таблицы
`stg.*_raw` хранят метаданные доставки Kafka вместе с именем читавшей ноды — `stg.*_raw` хранят метаданные доставки Kafka вместе с именем читавшей ноды —
+8 -8
View File
@@ -175,7 +175,7 @@ ENGINE = Distributed('clickstream_cluster', 'ods', 'event_errors_rep', cityHash6
-- --
-- items остаётся сырым фрагментом JSON: приём проверяет только, что это -- items остаётся сырым фрагментом JSON: приём проверяет только, что это
-- массив. Что внутри позиций — забота DDS, а не границы провода. -- массив. Что внутри позиций — забота DDS, а не границы провода.
CREATE TABLE IF NOT EXISTS ods.order_snapshot_rep ON CLUSTER clickstream_cluster CREATE TABLE IF NOT EXISTS ods.order_rep ON CLUSTER clickstream_cluster
( (
order_id String, order_id String,
user_id UInt64, user_id UInt64,
@@ -199,9 +199,9 @@ ORDER BY order_id;
-- и выбор здесь не про перекос, а про корректность: только так все версии -- и выбор здесь не про перекос, а про корректность: только так все версии
-- одного заказа попадают на один шард, и FINAL через распределённую таблицу -- одного заказа попадают на один шард, и FINAL через распределённую таблицу
-- выбирает одного победителя, а не по победителю на шард. -- выбирает одного победителя, а не по победителю на шард.
CREATE TABLE IF NOT EXISTS ods.order_snapshot_dist ON CLUSTER clickstream_cluster CREATE TABLE IF NOT EXISTS ods.order_dist ON CLUSTER clickstream_cluster
AS ods.order_snapshot_rep AS ods.order_rep
ENGINE = Distributed('clickstream_cluster', 'ods', 'order_snapshot_rep', cityHash64(order_id)); ENGINE = Distributed('clickstream_cluster', 'ods', 'order_rep', cityHash64(order_id));
-- Локальная таблица брака слепка. -- Локальная таблица брака слепка.
-- --
@@ -215,7 +215,7 @@ ENGINE = Distributed('clickstream_cluster', 'ods', 'order_snapshot_rep', cityHas
-- field_invalid. Имя провалившегося поля в класс не входит — сырой текст лежит -- field_invalid. Имя провалившегося поля в класс не входит — сырой текст лежит
-- рядом, и единичный случай разбирается по нему, без постоянной детализации -- рядом, и единичный случай разбирается по нему, без постоянной детализации
-- предиката (docs/architecture/orders/ingestion.md). -- предиката (docs/architecture/orders/ingestion.md).
CREATE TABLE IF NOT EXISTS ods.order_snapshot_errors_rep ON CLUSTER clickstream_cluster CREATE TABLE IF NOT EXISTS ods.order_errors_rep ON CLUSTER clickstream_cluster
( (
raw String, raw String,
error_class LowCardinality(String), error_class LowCardinality(String),
@@ -233,6 +233,6 @@ ORDER BY (error_class, kafka_partition, kafka_offset)
TTL toDateTime(_load_ts) + INTERVAL 1 MONTH TTL toDateTime(_load_ts) + INTERVAL 1 MONTH
SETTINGS ttl_only_drop_parts = 1; SETTINGS ttl_only_drop_parts = 1;
CREATE TABLE IF NOT EXISTS ods.order_snapshot_errors_dist ON CLUSTER clickstream_cluster CREATE TABLE IF NOT EXISTS ods.order_errors_dist ON CLUSTER clickstream_cluster
AS ods.order_snapshot_errors_rep AS ods.order_errors_rep
ENGINE = Distributed('clickstream_cluster', 'ods', 'order_snapshot_errors_rep', cityHash64(raw)); ENGINE = Distributed('clickstream_cluster', 'ods', 'order_errors_rep', cityHash64(raw));
+1 -1
View File
@@ -22,7 +22,7 @@ FROM ods.event_dist FINAL;
CREATE VIEW IF NOT EXISTS ods.order_v ON CLUSTER clickstream_cluster CREATE VIEW IF NOT EXISTS ods.order_v ON CLUSTER clickstream_cluster
AS AS
SELECT * SELECT *
FROM ods.order_snapshot_dist FINAL; FROM ods.order_dist FINAL;
-- ODS: разбор сырья в событие и в таблицу ошибок. -- ODS: разбор сырья в событие и в таблицу ошибок.
-- --
@@ -4,7 +4,7 @@
-- первый совпавший: скаляр проваливает и проверку на объект, и сверку ключей — -- первый совпавший: скаляр проваливает и проверку на объект, и сверку ключей —
-- без объявленного порядка он попал бы то в один класс, то в другой. -- без объявленного порядка он попал бы то в один класс, то в другой.
INSERT INTO ods.order_snapshot_errors_dist INSERT INTO ods.order_errors_dist
{% include "ods/_order_wire_contract.sql" %} {% include "ods/_order_wire_contract.sql" %}
SELECT SELECT
raw, raw,
@@ -4,7 +4,7 @@
-- Разобранные значения берёт assumeNotNull: обнуляемый разбор стоит за -- Разобранные значения берёт assumeNotNull: обнуляемый разбор стоит за
-- предикатом, который NULL уже отсёк, и приведение здесь не может упасть. -- предикатом, который NULL уже отсёк, и приведение здесь не может упасть.
INSERT INTO ods.order_snapshot_dist INSERT INTO ods.order_dist
{% include "ods/_order_wire_contract.sql" %} {% include "ods/_order_wire_contract.sql" %}
SELECT SELECT
JSONExtractString(raw, 'order_id') AS order_id, JSONExtractString(raw, 'order_id') AS order_id,