docs(dds): зафиксирована физическая модель карты идентичностей

- Зачем:
  - согласованная модель нужна для пакетной реализации DDS и понятного публичного интерфейса слоя.
- Что:
  - описаны физическая карта идентичностей, полный пересчёт и отказ от first_matched_at.
  - унифицирован публичный контракт _v для событий, заказов, сессий и карты.
  - синхронизированы мастер-спека, имена объектов и граница доступа.
- Проверка:
  - git diff --cached --check.
This commit is contained in:
ddadmin committed 2026-08-24 15:52:17 -04:00
1 parent 256d51840b
commit f0c4b4c627
7 files changed
+234 -59

No files matched your search

+22 -5
View File
@@ -36,7 +36,7 @@ CSV-файла. Живёт он вне цепочки слоёв, в зоне `d
| `_kafka` | таблица на движке `Kafka` |
| `_file` | таблица на движке `File` — чтец файла |
| `_mv` | материализованное представление |
| `_v` | обычное представление |
| `_v` | обычное представление, публичная поверхность чтения |
Суффикс носит каждый физический объект. Голого имени у таблицы не существует:
запрос к `stg.hits_raw` даёт громкую ошибку «нет такой таблицы» — а под голым
@@ -63,6 +63,23 @@ CSV-файла. Живёт он вне цепочки слоёв, в зоне `d
`order`, `session`. Граница между «как привезли» и «что это такое»
проходит по STG, и имена её показывают.
В DDS публичный договор сущности заканчивается на `_v`. Потребительские запросы
и витрины называют только представление; `_rep` и `_dist` остаются ролям
загрузки, диагностики и обслуживания. Представление перечисляет колонки явно,
даже если его запрос — простая проекция над `_dist`: договор не выдаёт
устройство кластера и случайно добавленные физической таблице колонки. У
события физической копии в DDS нет, но правило то же: `dds.event_v` — его
публичный договор.
Граница доступа — часть договора, а не следствие имени. Обычное представление
создаётся с явными `DEFINER = CURRENT_USER SQL SECURITY DEFINER`: определивший
его пользователь читает источники, потребительская роль получает `SELECT` на
`_v`, физические объекты — роль загрузки или диагностики. При стандартном
`INVOKER` потребителю нужны были бы права и на источник ([документация
ClickHouse](https://clickhouse.com/docs/sql-reference/statements/create/view#sql-security)).
Значит реализация публичной поверхности закончена, когда запрос
потребительской ролью проходит через `_v` и отклоняется для `_rep` и `_dist`.
## Раскладка по шардам
Пишем только в `_dist`. Локальные таблицы остаются для чтения и обслуживания —
@@ -98,10 +115,10 @@ FROM источник_dist`. Заводское значение `parallel_distr
Ключи ко-локации названы заранее, потому что на них стоит политика соединений из
раздела 6 спеки: обычное соединение разрешено только по ключу ко-локации, всё
прочее — через `GLOBAL`. Значит `dds.session` и `dds.identity_map` шардируются по
`cityHash64(ClientID)`. Объекты DDS с зерном заказа должны сохранять ко-локацию
по `cityHash64(order_id)`; ключи остальных частей будущей модели и витрин
появятся вместе с ними.
прочее — через `GLOBAL`. Значит `dds.session_dist` и `dds.identity_map_dist`
шардируются по `cityHash64(client_id)`. Объекты DDS с зерном заказа сохраняют
ко-локацию по `cityHash64(order_id)`; ключи остальных частей модели и витрин
появляются вместе с ними.
Замена партиций не используется для `ods.order`: версии прошлых дней
доливаются, а прямое чтение Kafka не задаёт границы полного слепка ([ADR