OLAP VS OLTP

OLTP vs OLAP на примере маркетплейса — и как я строю OLAP-хранилище (на примерах) Я — junior data engineer (~1 год опыта). Сначала — зачем разделять OLTP и OLAP, потом — как я реализую OLAP-слои на реальном кейсе маркетплейса.

Зачем разделяем (пример)

Ситуация: пользователь оплачивает заказ, списываются деньги, меняется остаток склада. — В OLTP важна мс-латентность и ACID: транзакция должна пройти «здесь и сейчас», иначе недовольный клиент. — Для вопроса «какой LTV у клиентов из города Х за 6 месяцев?» нужна история, агрегаты и длинные сканы — это OLAP. Если считать это в OLTP, GROUP BY по миллионам строк положит прод.

Как я строю OLAP-хранилище — слой за слоем, с примерами

  1. ODS — оперативный снимок из СИД

Что делаю: по расписанию забираю данные из источников (CRM, платежи, склад, приложение). Перед загрузкой очищаю ODS, чтобы хранить «как есть» за текущий цикл.

Пример: — Таблицы ods_orders, ods_payments, ods_stock, ods_users — ровно как в источнике: имена полей/типы совпадают, без бизнес-логики. — Если в CRM поле phone пришло в разном формате — в ODS не трогаю, это сырое зеркало.

  1. DDS_TMP — санитарная зона (временный слой)

Что делаю: привожу типы/форматы, чищу выбросы, дедуплицирую. Слой очищается перед каждой прогрузкой — хранит только текущую партию.

Пример: — Привожу created_at к UTC, amount к копейкам/центовым int. — Удаляю «двойные» платежи с одинаковым payment_id и суммой в одном батче. — Нормализую phone к E.164, валюты — к базовой.

  1. DDS (Data Vault) — слой историчности

Что делаю: пишу хабы/линки/спутники, никогда не очищаю — накапливаю версионную историю (SCD), обеспечиваю воспроизводимость.

Пример (фрагмент DV): — Hub_Customer (customer_hk, source_id, load_dts) — уникальная сущность клиента. — Link_Order связывает customer_hk и order_hk. — Sat_Order хранит изменяемые атрибуты заказа (статус, сумма, способ оплаты) с valid_from/valid_to. → Если заказ менял статус 4 раза — в Sat_Order будет 4 версии. Аналитика «как было на дату Х» становится тривиальной.

  1. DM + Dashboards — витрины под задачи

Что делаю: строю модели «звезда/снежинка» под конкретные вопросы бизнеса и BI. Перед каждой сборкой очищаю, чтобы получить согласованные результаты.

Пример витрин: — dm_sales_daily для план-факт по выручке и марже (факт + календарь + измерения «категория/регион/канал»). — dm_cohorts_ltv — коортная витрина для LTV/retention. — dm_ab_results — результат A/B-тестов (конверсия, ARPPU, p-value, лифт). Эти витрины идёт в Grafana/BI → дашборды «Категории/Регион», алерты «просела конверсия», отчёты С-level.

Вся цепочка на одном дыхании: OLTP → (CDC/батч) → ODS → DDS_TMP → DDS (Data Vault) → DM/Dashboards

Почему не считаю аналитику в OLTP (и примеры рисков)

Борьба за ресурсы: ночной отчёт LTV делает GROUP BY по кварталу — и платёжная форма начинает лагать.

Перерасход инфраструктуры: держать «и транзакции, и аналитику» в одном кластере — дорого и сложно масштабировать.

Борьба за данные: источники конфликтуют (дубликаты клиентов, разные справочники) — без ODS/DDS_TMP и контракта схемы всё превращается в хаос.

Рост конкуренции со временем: аналитика тяжелеет (больше историй/измерений) и всё чаще мешает пиковым оплатам.

Вывод (что я приношу бизнесу)

Я разделяю OLTP и OLAP и двигаю данные по цепочке ODS → DDS_TMP → DDS (Data Vault) → DM/Dashboards. На практике это означает: быстрый онбординг источников, прозрачная история изменений, предсказуемые SLA дашбордов и отсутствие войны за ресурсы с прод-транзакциями.