fix(ods): заказы разложены по своему ключу шардирования
- Зачем:
- заводское parallel_distributed_insert_select = 2 исполняло вставку из
Distributed в Distributed локально на каждом шарде, минуя ключ цели:
1189 из 1662 заказов задвоились на обоих шардах, а ReplacingMergeTree
через границу шарда дубли не схлопывает.
- Что:
- в обе вставки sql/ods/order_parse.sql добавлено явное
parallel_distributed_insert_select = 0 с доводом комментарием.
- в docs/architecture/storage.md описан капкан «INSERT из Distributed в
Distributed при несовпадающих ключах» и записана проверка (#137).
- Проверка:
- межшардовые дубли по ods.order_rep дают 0 (было 1189), каждый шард
держит только свои ключи; uniqExact(order_id) не изменился.
- после прожитого дага world_next_day новый слепок принят, дублей
по-прежнему 0.
- make smoke, make check-clickhouse.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
ea39982bdd
commit
8c76a7a0d8
2 files changed
+39
-2
No files matched your search
@@ -84,6 +84,19 @@ CSV-файла. Живёт он вне цепочки слоёв, в зоне `d
|
|||||||
Пошардовые счётчики STG и ODS поэтому не сходятся и сходиться не должны —
|
Пошардовые счётчики STG и ODS поэтому не сходятся и сходиться не должны —
|
||||||
сверять слои можно только через `_dist`.
|
сверять слои можно только через `_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 спеки: обычное соединение разрешено только по ключу ко-локации, всё
|
раздела 6 спеки: обычное соединение разрешено только по ключу ко-локации, всё
|
||||||
прочее — через `GLOBAL`. Значит `dds.session` и `dds.identity_map` шардируются по
|
прочее — через `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 подтвердил,
|
**Проверка версий заказов 18 августа 2026 года (#94).** MCP Context7 подтвердил,
|
||||||
что `JSONType` возвращает имя типа значения JSON, — на нём стоит проверка типов
|
что `JSONType` возвращает имя типа значения JSON, — на нём стоит проверка типов
|
||||||
в предикате приёма заказов. Остальное снято на закреплённом ClickHouse 26.3.
|
в предикате приёма заказов. Остальное снято на закреплённом ClickHouse 26.3.
|
||||||
|
|||||||
+16
-2
@@ -92,7 +92,16 @@ SELECT
|
|||||||
_load_ts
|
_load_ts
|
||||||
FROM stg.orders_raw_dist
|
FROM stg.orders_raw_dist
|
||||||
WHERE _load_id = {load_id:String} AND row_is_valid
|
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
|
_load_ts
|
||||||
FROM stg.orders_raw_dist
|
FROM stg.orders_raw_dist
|
||||||
WHERE _load_id = {load_id:String} AND NOT row_is_valid
|
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;
|
||||||
Reference in new issue
Block a user