diff --git a/dwh-modeling/README.md b/dwh-modeling/README.md index 1ea81df..afa07f5 100644 --- a/dwh-modeling/README.md +++ b/dwh-modeling/README.md @@ -316,175 +316,103 @@ fact_sales.order_date BETWEEN dim_customer.valid_from AND dim_customer.valid_to ### **3. Data Vault 2.0 — «конструктор Lego» для больших DWH** -*Идея: Дэн Линстедт (Dan Linstedt). Цель — собирать DWH из повторно используемых блоков, не боясь, что новый источник «сломает» всё, что было до него.* +*Идея: Дэн Линстедт (Dan Linstedt). Цель — так организовать хранилище, чтобы можно было спокойно добавлять новые источники и хранить историю, не ломая старую модель.* -#### С чего начать? Представьте конструктор +#### В чём идея, по-человечески -У вас есть коробка Lego. В ней: -- **Красные кирпичи (Хабы)** — это *«что или кто»*: клиент, заказ, товар. - У них нет цвета, надписей — только форма (бизнес-ключ). Главное — *узнать*, что это «один и тот же клиент №101», даже если его email менялся трижды. -- **Серые соединители (Линки)** — это *«как связаны»*: «заказ №5001 создан клиентом №101». - Не сами объекты, а *связь между ними*. И даже эту связь можно «отвязать» и привязать по-другому — без пересборки кирпичей. -- **Жёлтые наклейки (Сателлиты)** — это *«какие у них свойства»*: имя клиента, статус заказа, цена товара. - И самое важное: **каждый раз, когда что-то изменилось — наклеиваем новую новую наклейку**, не стирая старую. Так у нас остаётся *полная история*. +В Data Vault (DV) все сущности разлетаются по трём типам таблиц: -💡 **Главный принцип DV**: -> *«Идентичность — навсегда. Свойства — меняются. Связи — тоже могут меняться. И всё это — отдельно.»* +- **Hub (Хаб)** — *«кто/что это»*. + Только бизнес-ключ и технические поля: клиент, заказ, договор. -```mermaid -erDiagram - %% Хабы - красные кирпичи (идентичность) - %% Связи между компонентами - HUB_CUSTOMER ||--o{ SAT_CUSTOMER_INFO : "имеет" - HUB_CUSTOMER ||--o{ LINK_ORDER_CUSTOMER : "участвует_в" - HUB_ORDER ||--o{ LINK_ORDER_CUSTOMER : "создан" - LINK_ORDER_CUSTOMER ||--o{ SAT_ORDER_STATUS : "имеет_статус" +- **Link (Линк)** — *«как они связаны»*. + «Клиент сделал заказ», «договор относится к счёту». - HUB_CUSTOMER { - varchar customer_bk PK "Бизнес-ключ: '101'" - varchar record_source - timestamp load_dttm - } - - HUB_ORDER { - varchar order_id PK "Бизнес-ключ: '5001'" - varchar record_source - timestamp load_dttm - } - - %% Линки - серые соединители (связи) - LINK_ORDER_CUSTOMER { - varchar link_key PK "Хэш от (order_id+customer_bk)" - varchar order_id FK "→ HUB_ORDER" - varchar customer_bk FK "→ HUB_CUSTOMER" - varchar record_source - timestamp load_dttm - } - - %% Сателлиты - жёлтые наклейки (атрибуты + история) - SAT_CUSTOMER_INFO { - varchar customer_bk FK "→ HUB_CUSTOMER" - varchar hashdiff - timestamp valid_from - timestamp valid_to - varchar name - varchar email - varchar city - varchar record_source - timestamp load_dttm - } - - SAT_ORDER_STATUS { - varchar link_key FK "→ LINK_ORDER_CUSTOMER" - varchar hashdiff - timestamp valid_from - timestamp valid_to - varchar status - varchar record_source - timestamp load_dttm - } - -``` +- **Satellite (Сателлит)** — *«какие у них свойства и как они менялись»*. + Имя клиента, email, статус заказа, цены — всё с историей изменений. -> **Как читать схему:** -> 🔴 **Красные блоки (Хабы)** = «Кто/что это?» — только идентичность, никаких атрибутов. -> ⚪ **Серые блоки (Линки)** = «Как связаны?» — соединяют хабы, фиксируют отношения. -> 🟡 **Жёлтые блоки (Сателлиты)** = «Какие свойства?» — хранят атрибуты + историю изменений. -> -> 💡 **Правило конструктора:** Чтобы добавить новый источник (например, мобильное приложение), мы просто «приклеиваем» новый сателлит к существующему хабу — не перестраивая всю модель. +💡 **Главная мысль:** +идентичность, связи и атрибуты живут **в разных таблицах**, поэтому: +- историю проще хранить; +- новые источники проще прикручивать; +- меньше шансов «сломать» старые отчёты. --- -#### Почему это не просто SCD Type 2 «по-другому»? +#### Чем DV отличается от 3NF и Звезды -В SCD Type 2 (в `dim_customer`) мы *смешиваем*: -- идентичность (`customer_bk = 101`), -- и атрибуты (`email`, `city`), -- и связь с бизнес-событиями (`valid_from`, `is_current`). +Если сильно упростить: -В Data Vault эти три вещи **разнесены по разным таблицам**: -- `hub_customer` — только `customer_bk` и технические поля (откуда пришёл, когда загрузили); -- `sat_customer_info` — только атрибуты + их история (как в SCD, но отдельно!); -- `link_order_customer` — только «кто сделал заказ» (и даже тут — отдельный сателлит может хранить *статус связи*: «активный», «отменённый» и т.д.). +- В **3NF/Звезде** мы часто смешиваем: + - бизнес-ключ, + - текущие атрибуты, + - историю (SCD2) + — всё это в одной таблице измерения. -➡️ Это даёт **огромный бонус**: -Если завтра пришёл новый источник — например, мобильное приложение — и там у клиента есть `device_id`, -вы **не перестраиваете `dim_customer`** (как в Kimball/3NF), -а просто добавляете **новый сателлит** — `sat_customer_device`. -Старые отчёты продолжают работать. Новые — используют новую наклейку. +- В **Data Vault** это *разнесено*: + - Hub — только бизнес-ключ; + - Satellite — только атрибуты + история; + - Link — только связи между сущностями. + +За это приходится платить сложностью модели и количеством таблиц. Зато DV хорошо выдерживает: +- много разнородных источников; +- «грязные» данные; +- жёсткие требования по аудиту и трассировке. --- -#### Как устроен «сырой» Data Vault (упрощённо) +#### Raw Vault и Business Vault — два слоя -| Таблица | Внутри | Пример | -|---------|--------|--------| -| **`hub_customer`** | `customer_bk` (например, `'101'`) + `load_dttm` + `source` | Клиент «101» появился в CRM 10 января | -| **`sat_customer_info`** | `customer_bk`, `email`, `city`, `valid_from`, `valid_to`, `load_dttm` | 10 янв–15 мая: `a@ex.com`, Москва; 16 мая–…: `b@ex.com`, Москва | -| **`hub_order`** | `order_id` + `load_dttm` + `source` | Заказ «5001» из системы заказов | -| **`link_order_customer`** | `order_id`, `customer_bk` + `load_dttm` + `source` | Заказ 5001 → клиент 101 | -| **`sat_order_status`** *(опционально)* | `order_id`, `status`, `valid_from`, `valid_to` | 10 янв: «оплачен», 12 янв: «доставлен» | +Часто говорят «Raw Vault» и «Business Vault». Грубо: -> ⚠️ *На практике вместо `customer_bk` часто используют **хэш-ключ** (`hk_customer`) — чтобы сравнивать быстрее и избежать проблем с типами (число vs строка). +- **Raw Vault** — «как прилетело из источников». + Хабы, линкы и сателлиты, максимально близкие к исходным данным. + Задача: надёжно собрать и сохранить **полную историю**. + +- **Business Vault** — «как удобно считать дальше». + На основе Raw Vault появляются: + - служебные таблицы (PIT, Bridge и т.п.), + - подготовленные представления под витрины и отчёты, + - бизнес-правила (например, что считать «активным клиентом»). + +Дальше поверх этого уже строятся **обычные витрины в формате Звезды**, с которыми работают аналитики. + +Если примерить это к классическим слоям `stg → ods → dds → dm`, то **очень грубо** можно думать так: + +- `stg` всё равно остаётся как «приземление» (landing) из источников; +- **Raw Vault** по духу ближе к **ODS**: мало бизнес-логики, зато полная история и интеграция из разных систем; +- **Business Vault** ближе к **DDS**: здесь уже живут бизнес-правила и подготовка данных к витринам; +- `dm` по-прежнему остаётся витринами в формате Звезды, с которыми работают аналитики и BI. + +Важно: это именно *аналогия для понимания*, а не жёсткое правило проектирования. --- -#### А как же отчёты? Где витрины? +#### Когда DV вам, скорее всего, рано -Хороший вопрос. **Сырой DV — не для BI.** Это «склад запчастей». -Чтобы собрать «машину», нужен второй шаг: **Business Vault** (в DV 2.0 это — обязательная часть!). +Если у вас: -Там уже: -- **PIT-таблицы (Point-in-Time)** — «какой клиент был 12 января 2024?» за 1 JOIN, а не за 5 оконных функций; -- **Bridge-таблицы** — готовые пути: «заказ → клиент → последняя версия профиля»; -- **Derived-таблицы** — после бизнес-логики (скидки, сегментация, флаги). +- 2–5 источников, +- небольшая команда (1–2 инженера + аналитик), +- задачи уровня «сделать первые отчёты», -А *уже из них* строят **витрины в формате Звезды** — те самые `mart_daily_sales`, которые вы подключаете в Power BI. +то **Data Vault почти наверняка избыточен**. +Чаще всего хватает связки: -🔁 То есть цепочка: -**Источник → Hub/Link/Sat (Raw DV) → PIT/Bridge (Business Vault) → Star Schema (DM)** -Можно строить и напрямую, без PIT/Bridge таблиц. Но это значительно "тяжелее" с точки зрения затрат вычислительных ресурсов. +> `stg → ods → dds (3NF или простая Звезда с SCD2) → dm (Звезда)` --- -#### Плюсы и минусы — честно и без прикрас +#### Что важно запомнить из этой статьи -| ✅ Плюсы | ❌ Минусы | -|---------|----------| -| **История «из коробки»** — каждое изменение видно, ничего не перезаписывается | Сырой слой тяжел для чтения — нужен Business Vault (доп. работа) | -| **Добавить источник — легко** (новый сателлит, не ломая старое) | **Новых таблиц много** (Hub/Link/Sat — уже 3 на простую сущность) | -| **Полная трассировка**: кто, откуда, когда привёз каждую строчку | **Требует дисциплины**: если `record_source` забыли — аудит сломан | -| **Параллельная работа**: одна команда — клиенты, другая — заказы | **Не для MVP**: окупается на 10+ источниках, не на двух CSV | +Для этой статьи достаточно: ---- +- знать, что **Data Vault** — это способ строить хранилище как **конструктор из Hub/Link/Satellite**, +- понимать, что он нужен в первую очередь там, где: + - много систем-источников, + - нужна *полная* история и прозрачный аудит. -#### Когда Data Vault — ваш выбор? - -| Выберите DV 2.0, если… | Не начинайте с DV, если… | -|------------------------|---------------------------| -| У вас 5+ разнородных систем (CRM, ERP, мобильные приложения, внешние API) | У вас 1–2 источника и нужно быстро дать отчёт | -| Схемы часто меняются (новые атрибуты, новые связи) | Схема стабильна (например, учёт договоров в банке) | -| Важен аудит: «кто и когда изменил email?» (финтех, госсектор) | Отчёты — главная цель, а не соответствие регуляторам | -| В будущем — масштабирование: новые домены, новые команды | Вы один или вдвоём, и хотите простоты | - -> 🎯 **Совет для новичка**: -> Пока учитесь — *не пытайтесь собрать DV вручную*. Но **понимать его логику — обязательно**. -> Почему? Потому что многие современные enterprise-DWH сегодня — либо DV, либо гибриды (DV + Star). -> Даже если вы будете работать с витринами — вы будете *понимать*, откуда берутся данные и почему история «не обновляется». - ---- - -#### Важно: DV 1.0 vs DV 2.0 — в чём разница? - -- **DV 1.0** — только Hub/Link/Sat + историзация через `load_dttm`. - *Проблема:* нет стандартного способа хранить *периоды действия* (как в SCD Type 2) — `valid_from/valid_to` приходилось изобретать самим. - -- **DV 2.0** — стандартизирует: - - **Effectivity Satellites** (с `valid_from/valid_to`) — для явной историчности, - - **Multi-Active Satellites** — когда у объекта *несколько одновременных значений* (например, три активных телефона), - - **Business Vault** — как обязательный слой перед витринами. - -➡️ Сегодня, когда говорят «Data Vault», почти всегда имеют в виду **DV 2.0**. +Детали (Raw vs Business Vault, PIT/Bridge, DV 1.0 vs 2.0 и т.п.) — это уже тема для отдельной, взрослой статьи. ---