Вычитка статьи
This commit is contained in:
+163
-37
@@ -296,39 +296,177 @@ fact_sales.order_date BETWEEN dim_customer.valid_from AND dim_customer.valid_to
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### **3. Data Vault 2.0**
|
### **3. Data Vault 2.0 — «конструктор Lego» для больших DWH**
|
||||||
*Источник: Дэн Линстедт (Dan Linstedt)*
|
|
||||||
|
|
||||||
Модель основана на трёх типах таблиц:
|
*Идея: Дэн Линстедт (Dan Linstedt). Цель — собирать DWH из повторно используемых блоков, не боясь, что новый источник «сломает» всё, что было до него.*
|
||||||
|
|
||||||
| Тип | Назначение | Пример |
|
#### С чего начать? Представьте конструктор
|
||||||
|-----|------------|--------|
|
|
||||||
| **Hub (Хаб)** | Хранит бизнес-ключи (BK) | `hub_customer`: `customer_id`, `load_dttm` |
|
У вас есть коробка Lego. В ней:
|
||||||
| **Link (Связь)** | Фиксирует отношения | `link_order_customer`: `order_id + customer_id` |
|
- **Красные кирпичи (Хабы)** — это *«что или кто»*: клиент, заказ, товар.
|
||||||
| **Satellite (Сателлит)** | Хранит атрибуты + историю | `sat_customer_info`: имя, email, дата начала/окончания |
|
У них нет цвета, надписей — только форма (бизнес-ключ). Главное — *узнать*, что это «один и тот же клиент №101», даже если его email менялся трижды.
|
||||||
|
- **Серые соединители (Линки)** — это *«как связаны»*: «заказ №5001 создан клиентом №101».
|
||||||
|
Не сами объекты, а *связь между ними*. И даже эту связь можно «отвязать» и привязать по-другому — без пересборки кирпичей.
|
||||||
|
- **Жёлтые наклейки (Сателлиты)** — это *«какие у них свойства»*: имя клиента, статус заказа, цена товара.
|
||||||
|
И самое важное: **каждый раз, когда что-то изменилось — наклеиваем новую жёлтую наклейку**, не стирая старую. Так у нас остаётся *полная история*.
|
||||||
|
|
||||||
|
💡 **Главный принцип DV**:
|
||||||
|
> *«Идентичность — навсегда. Свойства — меняются. Связи — тоже могут меняться. И всё это — отдельно.»*
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
erDiagram
|
erDiagram
|
||||||
hub_customer ||--o{ sat_customer_info : "хаб → сателлит"
|
%% Хабы - красные кирпичи (идентичность)
|
||||||
hub_order ||--o{ sat_order_details : "хаб → сателлит"
|
%% Связи между компонентами
|
||||||
hub_customer ||--o{ link_order_customer : "участвует в"
|
HUB_CUSTOMER ||--o{ SAT_CUSTOMER_INFO : "имеет"
|
||||||
hub_order ||--o{ link_order_customer : "создан клиентом"
|
HUB_CUSTOMER ||--o{ LINK_ORDER_CUSTOMER : "участвует_в"
|
||||||
|
HUB_ORDER ||--o{ LINK_ORDER_CUSTOMER : "создан"
|
||||||
|
LINK_ORDER_CUSTOMER ||--o{ SAT_ORDER_STATUS : "имеет_статус"
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
✅ **Плюсы**:
|
> **Как читать схему:**
|
||||||
- **История «из коробки»** — каждое изменение — новая строка в сателлите;
|
> 🔴 **Красные блоки (Хабы)** = «Кто/что это?» — только идентичность, никаких атрибутов.
|
||||||
- **Масштабируемость**: легко подключить новый источник — добавили хаб/линк/сателлит;
|
> ⚪ **Серые блоки (Линки)** = «Как связаны?» — соединяют хабы, фиксируют отношения.
|
||||||
- **Аудит**: откуда пришёл каждый факт — видно по `_load_dttm`.
|
> 🟡 **Жёлтые блоки (Сателлиты)** = «Какие свойства?» — хранят атрибуты + историю изменений.
|
||||||
|
>
|
||||||
|
> 💡 **Правило конструктора:** Чтобы добавить новый источник (например, мобильное приложение), мы просто «приклеиваем» новый сателлит к существующему хабу — не перестраивая всю модель.
|
||||||
|
|
||||||
❌ **Минусы**:
|
---
|
||||||
- Сложно читать (20 таблиц вместо 3);
|
|
||||||
- Нужно писать сложные запросы (или использовать автоматическую генерацию витрин).
|
|
||||||
|
|
||||||
📌 **Когда выбирать**:
|
#### Почему это не просто SCD Type 2 «по-другому»?
|
||||||
→ Большие проекты с 10+ источниками;
|
|
||||||
→ Когда критична **трассировка** и **соответствие регуляторным требованиям** (например, финтех).
|
|
||||||
|
|
||||||
> 📌 *DV 1.0* не поддерживал SCD Type 2 «из коробки» — в DV 2.0 это решено.
|
В 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` — только «кто сделал заказ» (и даже тут — отдельный сателлит может хранить *статус связи*: «активный», «отменённый» и т.д.).
|
||||||
|
|
||||||
|
➡️ Это даёт **огромный бонус**:
|
||||||
|
Если завтра пришёл новый источник — например, мобильное приложение — и там у клиента есть `device_id`,
|
||||||
|
вы **не перестраиваете `dim_customer`** (как в Kimball/3NF),
|
||||||
|
а просто добавляете **новый сателлит** — `sat_customer_device`.
|
||||||
|
Старые отчёты продолжают работать. Новые — используют новую наклейку.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Как устроен «сырой» Data 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 янв: «доставлен» |
|
||||||
|
|
||||||
|
> ⚠️ *На практике вместо `customer_bk` часто используют **хэш-ключ** (`hk_customer`) — чтобы сравнивать быстрее и избежать проблем с типами (число vs строка).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### А как же отчёты? Где витрины?
|
||||||
|
|
||||||
|
Хороший вопрос. **Сырой DV — не для BI.** Это «склад запчастей».
|
||||||
|
Чтобы собрать «машину», нужен второй шаг: **Business Vault** (в DV 2.0 это — обязательная часть!).
|
||||||
|
|
||||||
|
Там уже:
|
||||||
|
- **PIT-таблицы (Point-in-Time)** — «какой клиент был 12 января 2024?» за 1 JOIN, а не за 5 оконных функций;
|
||||||
|
- **Bridge-таблицы** — готовые пути: «заказ → клиент → последняя версия профиля»;
|
||||||
|
- **Derived-таблицы** — после бизнес-логики (скидки, сегментация, флаги).
|
||||||
|
|
||||||
|
А *уже из них* строят **витрины в формате Звезды** — те самые `mart_daily_sales`, которые вы подключаете в Power BI.
|
||||||
|
|
||||||
|
🔁 То есть цепочка:
|
||||||
|
**Источник → Hub/Link/Sat (Raw DV) → PIT/Bridge (Business Vault) → Star Schema (DM)**
|
||||||
|
Можно строить и напрямую, без PIT/Bridge таблиц. Но это значительно "тяжелее" с точки зрения затрат вычислительных ресурсов.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Плюсы и минусы — честно и без прикрас
|
||||||
|
|
||||||
|
| ✅ Плюсы | ❌ Минусы |
|
||||||
|
|---------|----------|
|
||||||
|
| **История «из коробки»** — каждое изменение видно, ничего не перезаписывается | Сырой слой тяжел для чтения — нужен Business Vault (доп. работа) |
|
||||||
|
| **Добавить источник — легко** (новый сателлит, не ломая старое) | **Новых таблиц много** (Hub/Link/Sat — уже 3 на простую сущность) |
|
||||||
|
| **Полная трассировка**: кто, откуда, когда привёз каждую строчку | **Требует дисциплины**: если `record_source` забыли — аудит сломан |
|
||||||
|
| **Параллельная работа**: одна команда — клиенты, другая — заказы | **Не для MVP**: окупается на 10+ источниках, не на двух CSV |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### Когда 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**.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -377,7 +515,7 @@ quadrantChart
|
|||||||
|
|
||||||
## **7. Практикум: как собрать первую витрину**
|
## **7. Практикум: как собрать первую витрину**
|
||||||
|
|
||||||
Покажем на примере `mart_daily_sales` — таблицу, которую можно сразу подключить к Power BI.
|
Покажем на примере `mart_daily_sales` — таблицу, которую можно сразу подключить к BI.
|
||||||
|
|
||||||
### **Этапы сборки**
|
### **Этапы сборки**
|
||||||
|
|
||||||
@@ -454,7 +592,7 @@ GROUP BY d.date_actual, p.product_name, c.customer_segment;
|
|||||||
|
|
||||||
1. **Начните с витрины в формате Звезды (Star Schema).**
|
1. **Начните с витрины в формате Звезды (Star Schema).**
|
||||||
— Это просто: одна таблица фактов + несколько «плоских» справочников.
|
— Это просто: одна таблица фактов + несколько «плоских» справочников.
|
||||||
— Это быстро: отчёт в Power BI — за 10 минут.
|
— Это быстро: отчёт в BI — за 10 минут.
|
||||||
— Это понятно: даже менеджер поймёт структуру.
|
— Это понятно: даже менеджер поймёт структуру.
|
||||||
|
|
||||||
2. **Стройте DDS только когда это *действительно нужно*.**
|
2. **Стройте DDS только когда это *действительно нужно*.**
|
||||||
@@ -607,18 +745,6 @@ SELECT 'OK' WHERE EXISTS (
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 📖 Что почитать дальше?
|
|
||||||
|
|
||||||
| Книга / Ресурс | Для кого |
|
|
||||||
|----------------|----------|
|
|
||||||
| **Кимболл, «Техника создания хранилищ данных»** | Начинающим: звезда, SCD, витрины |
|
|
||||||
| **Инмон, «Построение хранилищ данных»** | Для понимания 3NF и корпоративного подхода |
|
|
||||||
| **Linstedt & Olschimke, «Data Vault 2.0»** | Практическое руководство по DV |
|
|
||||||
| **[anchor-modeling.com](https://www.anchormodeling.com/)** | Официальный сайт Anchor Modeling |
|
|
||||||
| **Курс «Аналитика в Postgres» (Stepik / Postgres Pro)** | Практика SQL + DWH на реальных данных |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## **ЧАСТЬ C. Мини-датасет (для практики)**
|
## **ЧАСТЬ C. Мини-датасет (для практики)**
|
||||||
|
|
||||||
Положите эти файлы в папку `data/` — и тренируйтесь:
|
Положите эти файлы в папку `data/` — и тренируйтесь:
|
||||||
|
|||||||
Reference in New Issue
Block a user