Зачем: помочь начинающему инженеру проследить событие и версию заказа от генератора до хранилища, включая ошибки и повторные поступления. Что: обновлены вводная генератора, справочники приема и модели заказа, разделы хранилища и комментарии SQL и дага. Сохранены технические условия; исполняемый код, схемы и поведение стенда не изменены. Проверка: make lint, git diff --check, 142 локальные ссылки и справка CLI. SQL без комментариев и Python AST без строк документации совпали с исходными. Генерация данных и сброс состояния не выполнялись. Refs #250
8.2 KiB
Модель заказа в DDS
DDS готовит заказ для анализа: выбирает текущее состояние из ODS, разбирает позиции и переводит время в часовой пояс счетчика. Этот слой показывает, как собрать модель данных для витрин и повторить загрузку без удвоения заказов.
Зерно
Одна строка — один заказ в последнем известном состоянии, ключ — order_id.
История изменений здесь не хранится. ODS тоже не служит ее архивом:
промежуточные версии удаляются при фоновых слияниях.
Состав строки
Поля заказа приходят из ods.order_v с именами источника: order_id,
user_id, status, items_total, discount, delivery, total.
Денежные колонки хранят рубли с копейками в Decimal(18, 2).
created_at и updated_at переводятся из UTC в Europe/Samara, пояс
счетчика сайта. Из created_at в этом поясе вычисляется order_date —
день оформления заказа. Витрины группируют по готовой дате;
правило времени общее для хранилища.
Строка items из ODS разбирается в три массива одной длины:
| Колонка | Что хранит |
|---|---|
item_sku |
Артикулы товаров |
item_quantity |
Количество каждого товара, UInt32 |
item_price |
Цены за единицу в рублях, Decimal(18, 2) |
Элементы с одинаковым номером описывают одну позицию заказа. Витрина
выручки разворачивает их через ARRAY JOIN и получает категорию товара
из справочника через dictGet. Разбор JSON выполняется один раз
при загрузке DDS.
ODS проверяет только то, что items — массив. Разбор в DDS не заменяет
проверку его содержимого: например, некорректное количество может стать
нулем. Проверку суммы позиций участник добавляет в
первом задании ступени 5.
Движок и наполнение
dds.order_rep — таблица на ReplicatedMergeTree, без колонки версии.
Партиция хранит один order_date, ключ сортировки — order_id.
Запись через dds.order_dist распределяет заказы по cityHash64(order_id),
как в ODS. Для чтения служит dds.order_v с явным списком колонок
над dds.order_dist; FINAL в этом слое не нужен.
Даг dds_transform пересобирает выбранные дни из ods.order_v:
order_scope.sqlопределяет непрерывный отрезокfirst_day…last_day. Он включает дни заказов из последнего слепка и начинается раньше, если в DDS отсутствует день, который есть в ODS.order_rebuild.sqlочищает промежуточную таблицуdds.order_stage_repи наполняет ее черезdds.order_stage_dist. Это донор: в нем готовится результат, пока основная таблица остается доступной для чтения.order_replace.sqlзаменяет каждую дневную партицию основной таблицы готовой партицией донора.
Повтор при неизменном ODS дает те же деловые данные без дублей — это идемпотентность загрузки. Пока заказы дня входят в семидневное окно источника, их состояние может меняться, и день пересобирается. За пределами окна новые состояния не приходят, но пропущенный день можно восстановить из ODS. Границы пересборки берутся из данных; число семь в SQL хранилища не повторяется.
Замена атомарна внутри одного шарда: читатель видит прежнюю или новую партицию целиком. Замены на двух шардах независимы, поэтому между ними запрос через Distributed может увидеть смешанный результат. Донор остается до следующей сборки и доступен для диагностики. Порядок задач и повторы — в описании дневного конвейера.
Служебные колонки
_load_id и _load_ts показывают, какой запуск DDS собрал строку
и когда он выполнил вставку. Они одинаковы у строк одной сборки.
При следующей пересборке эти метки обновятся, даже если заказ не изменился.
snapshot_date и метки приема ODS в DDS не переносятся: они описывают
получение сообщения источника. Их можно найти в ODS по order_id.
В каждом слое служебные колонки относятся к его собственной загрузке.
При поиске ошибки начните с _load_id в DDS: он указывает на запуск
сборки. По order_id найдите версии заказа в ODS, а по их _load_id —
соответствующие сырые сообщения в STG и ошибки того же приема.
В таблице ошибок order_id может быть не разобран, поэтому нужное
сообщение ищут по raw и координатам Kafka.
Сырые сообщения хранятся около трех реальных суток, ошибки — месяц;
уточнения к срокам — в справочнике хранилища.
Читатели
dm.revenue_daily_vсчитает выручку по заказам со статусомpaid, разворачивает позиции и дополняет их категорией товара.dm.purchase_vs_orders_vсопоставляет заказ с покупкой на сайте поorder_id, используяorder_date,items_totalиstatus.dds.identity_mapсвязывает идентификаторы посетителей сuser_idчерез покупки и заказы.
Связанные решения
- ADR 0010 — версии заказов в ODS
и чтение через
ods.order_v. - Прием заказов — проверки формата и выбор актуальной версии.
- Исследование соединений —
почему сверка распределенных источников использует
GLOBAL JOIN. - Проталкивание условий сквозь представления — как фильтр запроса влияет на объем чтения ODS.