diff --git a/docs/architecture/storage.md b/docs/architecture/storage.md index d88b19c..afca243 100644 --- a/docs/architecture/storage.md +++ b/docs/architecture/storage.md @@ -84,6 +84,19 @@ CSV-файла. Живёт он вне цепочки слоёв, в зоне `d Пошардовые счётчики STG и ODS поэтому не сходятся и сходиться не должны — сверять слои можно только через `_dist`. +Разные ключи у слоёв ставят капкан на вставке `INSERT INTO цель_dist SELECT … +FROM источник_dist`. Заводское значение `parallel_distributed_insert_select` — +2: если обе таблицы на одном кластере, вставка исполняется локально на каждом +шарде, и шард пишет прямо в локальную таблицу цели, минуя её ключ шардирования. +Строки наследуют раскладку источника, и ошибки при этом нет: расхождение видно +только пересчётом по `hostName()` — сколько ключей встретилось больше чем на +одном шарде. На разборе заказов так и вышло: 1189 из 1662 заказов легли +одинаковыми строками на оба шарда, а `ReplacingMergeTree` через границу шарда их +не схлопывает. Поэтому у такой вставки в `SETTINGS` стоит явное +`parallel_distributed_insert_select = 0`: раскладку делает инициатор, по ключу +цели (`sql/ods/order_parse.sql`). Правило нужно и дальше — сборки DDS тоже будут +читать `_dist` и писать в `_dist` с другим ключом. + Ключи ко-локации названы заранее, потому что на них стоит политика соединений из раздела 6 спеки: обычное соединение разрешено только по ключу ко-локации, всё прочее — через `GLOBAL`. Значит `dds.session` и `dds.identity_map` шардируются по @@ -573,6 +586,16 @@ DDL-словарь с файловым источником внутри `user_f разобрано, почему отказ в праве на движок называет не то право, которого не хватает. +**Проверка ко-локации заказов 22 августа 2026 года (#137).** Context7 и +`system.settings` закреплённого ClickHouse 26.3 назвали одну и ту же тройку +значений `parallel_distributed_insert_select`: `0` — выключено, `1` — `SELECT` +на каждом шарде, `2` — `SELECT` и `INSERT` на каждом шарде; заводское — `2`. +На живых данных видны и дефект, и починка: до правки 1189 из 1662 заказов +лежали на обоих шардах, после явного нуля и повторного разбора того же +`_load_id` — ни одного, каждый шард держит только свои ключи. Вершина версий +уцелела: деловые поля `ods.order_v` сошлись с эталоном, посчитанным прямо из +сырья. + **Проверка версий заказов 18 августа 2026 года (#94).** MCP Context7 подтвердил, что `JSONType` возвращает имя типа значения JSON, — на нём стоит проверка типов в предикате приёма заказов. Остальное снято на закреплённом ClickHouse 26.3. diff --git a/sql/ods/order_parse.sql b/sql/ods/order_parse.sql index 0600773..e54c9e6 100644 --- a/sql/ods/order_parse.sql +++ b/sql/ods/order_parse.sql @@ -92,7 +92,16 @@ SELECT _load_ts FROM stg.orders_raw_dist WHERE _load_id = {load_id:String} AND row_is_valid -SETTINGS distributed_foreground_insert = 1; +-- Заводское значение parallel_distributed_insert_select — 2: вставку вида +-- INSERT ... SELECT из Distributed в Distributed на одном кластере ClickHouse +-- исполняет локально на каждом шарде, и строки минуют ключ шардирования цели. +-- Ключи здесь разные — сырьё разложено по хешу строки, заказы по +-- cityHash64(order_id), — так версии одного заказа и расползлись по обоим +-- шардам, где ReplacingMergeTree их уже не схлопывает. Ноль возвращает вставку +-- инициатору: он читает срез со всех шардов и пишет через ods.order_dist, +-- то есть по её ключу. +SETTINGS distributed_foreground_insert = 1, + parallel_distributed_insert_select = 0; -- Брак: тот же срез и буквальное отрицание того же предиката. -- @@ -118,4 +127,9 @@ SELECT _load_ts FROM stg.orders_raw_dist WHERE _load_id = {load_id:String} AND NOT row_is_valid -SETTINGS distributed_foreground_insert = 1; +-- Тот же ноль, хотя здесь заводское значение раскладку не ломало: ключ у +-- ods.order_errors_dist — cityHash64(raw), тот же, что у сырья, и локальная +-- запись попадала бы в свой шард сама. Совпадение ключей не гарантия: +-- поменяется ключ любой из двух таблиц — и строки разъедутся молча. +SETTINGS distributed_foreground_insert = 1, + parallel_distributed_insert_select = 0;