From 3cbaeb5fc27fbc1c3fdc6c8c53722972fa53b943 Mon Sep 17 00:00:00 2001 From: Dmitry Dementev Date: Sat, 8 Nov 2025 20:42:35 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=B8=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D1=81=D0=BA=D1=80?= =?UTF-8?q?=D0=B8=D0=BF=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dwh-modeling/dimensions_sample.sql | 255 -------- dwh-modeling/dwh-modeling-basics.md | 288 --------- dwh-modeling/dwh-modeling-ds.md | 549 ----------------- dwh-modeling/dwh-modeling-plan3.md | 570 ------------------ .../sql/{01_ddl.sql => 01_ddl_stg-dds.sql} | 0 .../sql/{02_dim.sql => 02_dml_stg-dds.sql} | 0 6 files changed, 1662 deletions(-) delete mode 100644 dwh-modeling/dimensions_sample.sql delete mode 100644 dwh-modeling/dwh-modeling-basics.md delete mode 100644 dwh-modeling/dwh-modeling-ds.md delete mode 100644 dwh-modeling/dwh-modeling-plan3.md rename dwh-modeling/sql/{01_ddl.sql => 01_ddl_stg-dds.sql} (100%) rename dwh-modeling/sql/{02_dim.sql => 02_dml_stg-dds.sql} (100%) diff --git a/dwh-modeling/dimensions_sample.sql b/dwh-modeling/dimensions_sample.sql deleted file mode 100644 index 7bf01ab..0000000 --- a/dwh-modeling/dimensions_sample.sql +++ /dev/null @@ -1,255 +0,0 @@ --- =============================================== --- 1. Создание схем --- =============================================== -DROP SCHEMA IF EXISTS stg CASCADE; -DROP SCHEMA IF EXISTS ods CASCADE; -DROP SCHEMA IF EXISTS dds CASCADE; -CREATE SCHEMA stg; -CREATE SCHEMA ods; -CREATE SCHEMA dds; - --- =============================================== --- 2. STG: таблицы «как пришло» --- =============================================== - --- Сырые данные: строки, как из CSV/API -CREATE TABLE stg.customers_raw ( - customer_id TEXT, -- может быть '101' или 'CUST-101' - email TEXT, - phone TEXT, - city TEXT, - _load_ts TIMESTAMP DEFAULT NOW() -); - -CREATE TABLE stg.orders_raw ( - order_id TEXT, - order_date TEXT, -- формат: '2024-01-10' - customer_id TEXT -); - -CREATE TABLE stg.order_items_raw ( - order_item_id TEXT, - order_id TEXT, - product_id TEXT, - qty TEXT, -- может быть '2', 'NULL' - price_at_sale TEXT -- может быть '100.00' -); - -CREATE TABLE stg.products_raw ( - product_id TEXT, - name TEXT -); - --- Загрузка тестовых данных (вместо COPY FROM CSV) -INSERT INTO stg.customers_raw (customer_id, email, phone, city) VALUES -('101', 'a@ex.com', '700', 'Москва'), -('101', 'b@ex.com', '700', 'Москва'), -- изменение email -('102', 'c@ex.com', '701', 'СПб'); - -INSERT INTO stg.orders_raw (order_id, order_date, customer_id) VALUES -('5001', '2024-01-10', '101'), -('5002', '2024-02-05', '102'); - -INSERT INTO stg.order_items_raw (order_item_id, order_id, product_id, qty, price_at_sale) VALUES -('1', '5001', '9001', '2', '100.00'), -('2', '5001', '9002', '1', '50.00'), -('3', '5002', '9001', '1', '100.00'); - -INSERT INTO stg.products_raw (product_id, name) VALUES -('9001', 'Phone'), -('9002', 'Case'); - --- =============================================== --- 3. ODS: очистка и типизация --- =============================================== - --- Очищенные клиенты -CREATE TABLE ods.customers AS -SELECT - customer_id::INT AS customer_id, -- приведение к INT - NULLIF(TRIM(email), '') AS email, -- пустые → NULL - NULLIF(TRIM(phone), '') AS phone, - NULLIF(TRIM(city), '') AS city -FROM stg.customers_raw -WHERE customer_id ~ '^\d+$'; -- валидация: только цифры - --- Очищенные заказы -CREATE TABLE ods.orders AS -SELECT - order_id::INT, - TO_DATE(order_date, 'YYYY-MM-DD') AS order_date, - customer_id::INT -FROM stg.orders_raw -WHERE order_date IS NOT NULL AND customer_id ~ '^\d+$'; - --- Очищенные позиции заказа -CREATE TABLE ods.order_items AS -SELECT - order_item_id::INT, - order_id::INT, - product_id::INT, - NULLIF(qty, '')::INT AS qty, - NULLIF(price_at_sale, '')::NUMERIC(10,2) AS price_at_sale -FROM stg.order_items_raw -WHERE qty ~ '^\d+$' AND price_at_sale ~ '^\d+(\.\d+)?$'; - --- Очищенные товары -CREATE TABLE ods.products AS -SELECT - product_id::INT, - TRIM(name) AS name -FROM stg.products_raw -WHERE product_id ~ '^\d+$'; - --- Добавим первичные ключи (для ускорения JOIN и проверки) -ALTER TABLE ods.customers ADD PRIMARY KEY (customer_id); -ALTER TABLE ods.orders ADD PRIMARY KEY (order_id); -ALTER TABLE ods.order_items ADD PRIMARY KEY (order_item_id); -ALTER TABLE ods.products ADD PRIMARY KEY (product_id); - --- =============================================== --- 4. DDS: интеграция + SCD Type 2 --- =============================================== - --- 4.1 dim_date — справочник дат (на 5 лет: 2023–2027) -CREATE TABLE dds.dim_date AS -WITH RECURSIVE dates AS ( - SELECT DATE '2023-01-01' AS d - UNION ALL - SELECT d + INTERVAL '1 day' - FROM dates - WHERE d + INTERVAL '1 day' <= DATE '2027-12-31' -) -SELECT - CAST(TO_CHAR(d, 'YYYYMMDD') AS INT) AS date_key, - d AS date_actual, - EXTRACT(YEAR FROM d) AS year, - EXTRACT(QUARTER FROM d) AS quarter, - EXTRACT(MONTH FROM d) AS month, - EXTRACT(DAY FROM d) AS day, - TO_CHAR(d, 'Day') AS weekday_name, - EXTRACT(DOW FROM d) AS weekday_num, -- 0 = воскресенье - d BETWEEN - DATE_TRUNC('month', d) - AND DATE_TRUNC('month', d) + INTERVAL '1 month' - INTERVAL '1 day' - AND EXTRACT(DAY FROM d) <= 7 - AS is_first_week -FROM dates; - -ALTER TABLE dds.dim_date ADD PRIMARY KEY (date_key); - --- 4.2 dim_product — измерение «Товар» (без истории — атрибуты стабильны) -CREATE TABLE dds.dim_product ( - product_sk BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, - product_bk INT NOT NULL, - product_name VARCHAR(100) NOT NULL -); - -INSERT INTO dds.dim_product (product_bk, product_name) -SELECT product_id, name -FROM ods.products; - --- 4.3 dim_customer — SCD Type 2 (с историей) -CREATE TABLE dds.dim_customer ( - customer_sk BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, - customer_bk INT NOT NULL, - email VARCHAR(100), - phone VARCHAR(20), - city VARCHAR(50), - valid_from DATE NOT NULL, - valid_to DATE NOT NULL DEFAULT '9999-12-31', - is_current BOOLEAN NOT NULL DEFAULT TRUE -); - --- Загрузка первой версии (SCD Type 2 — простой алгоритм) --- Группируем по customer_bk и сортируем по времени (по _load_ts из STG) --- Для учебного примера имитируем хронологию через порядок строк -WITH ranked AS ( - SELECT - customer_id AS customer_bk, - email, - phone, - city, - ROW_NUMBER() OVER ( - PARTITION BY customer_id - ORDER BY _load_ts, email -- хронология изменений - ) AS rn - FROM stg.customers_raw - WHERE customer_id ~ '^\d+$' -), -changes AS ( - SELECT - customer_bk, - email, - phone, - city, - -- начальная дата — день первого появления в источнике - '2023-01-01'::DATE + (rn - 1) * INTERVAL '1 day' AS eff_from - FROM ranked -), -final AS ( - SELECT - customer_bk, - email, - phone, - city, - eff_from::DATE AS valid_from, - COALESCE( - LEAD(eff_from) OVER (PARTITION BY customer_bk ORDER BY eff_from) - INTERVAL '1 day', - '9999-12-31'::DATE - ) AS valid_to, - CASE WHEN - LEAD(eff_from) OVER (PARTITION BY customer_bk ORDER BY eff_from) IS NULL - THEN TRUE ELSE FALSE END AS is_current - FROM changes -) -INSERT INTO dds.dim_customer (customer_bk, email, phone, city, valid_from, valid_to, is_current) -SELECT customer_bk, email, phone, city, valid_from, valid_to, is_current -FROM final; - --- 4.4 fact_sales — факт продаж -CREATE TABLE dds.fact_sales ( - sale_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, - customer_sk BIGINT NOT NULL, -- ссылка на DDS-измерение - product_sk BIGINT NOT NULL, - date_key INT NOT NULL, -- YYYYMMDD - quantity INT NOT NULL CHECK (quantity > 0), - amount NUMERIC(18,2) NOT NULL CHECK (amount >= 0) -); - --- Заполнение fact_sales с учётом истории клиента (SCD!) -INSERT INTO dds.fact_sales (customer_sk, product_sk, date_key, quantity, amount) -SELECT - dc.customer_sk, - dp.product_sk, - CAST(TO_CHAR(o.order_date, 'YYYYMMDD') AS INT) AS date_key, - oi.qty, - oi.price_at_sale * oi.qty AS amount -FROM ods.orders o -JOIN ods.order_items oi ON o.order_id = oi.order_id -JOIN ods.products p ON oi.product_id = p.product_id -JOIN dds.dim_product dp ON p.product_id = dp.product_bk -JOIN dds.dim_customer dc - ON o.customer_id = dc.customer_bk - AND o.order_date BETWEEN dc.valid_from AND dc.valid_to; -- ← ключевая строка SCD! - --- Добавим внешние ключи (опционально, для целостности) -ALTER TABLE dds.fact_sales - ADD FOREIGN KEY (customer_sk) REFERENCES dds.dim_customer(customer_sk), - ADD FOREIGN KEY (product_sk) REFERENCES dds.dim_product(product_sk), - ADD FOREIGN KEY (date_key) REFERENCES dds.dim_date(date_key); - --- =============================================== --- 5. Проверка: посчитаем выручку по клиентам --- =============================================== -SELECT - dc.customer_bk, - dc.email, - dc.city, - SUM(f.amount) AS total_revenue -FROM dds.fact_sales f -JOIN dds.dim_customer dc - ON f.customer_sk = dc.customer_sk - AND dc.is_current -- только актуальная версия -GROUP BY dc.customer_bk, dc.email, dc.city -ORDER BY total_revenue DESC; diff --git a/dwh-modeling/dwh-modeling-basics.md b/dwh-modeling/dwh-modeling-basics.md deleted file mode 100644 index 3bbf47b..0000000 --- a/dwh-modeling/dwh-modeling-basics.md +++ /dev/null @@ -1,288 +0,0 @@ -# Структура хранилища данных (для студентов SQL/Postgres) - -> **Цель**: объяснить, как раскладывать данные в аналитической БД и почему именно так принято. Рус/Eng термины приводятся вместе (например, «витрина (Data Mart)»). -Статья для учениковп про то, чтобы понимать модели и уметь пользоваться моделированнаыми хранилищами, знать их структуру. У нее нет цели научить проектировать хранилища. Цель - научить понимать структуру и ее смысл - ---- - -## 0. Навигация по статье - -* [1. Введение: зачем слои и почему не «всё в одну таблицу»](#1) -* [2. Учебный домен/пример](#2) -* [3. Типичная структура слоёв (STG → ODS → DDS → DM)](#3) -* [4. Слои по отдельности](#4) -* [5. Модели данных для DDS/DM: 3NF, Звезда/Снежинка, Data Vault, Anchor](#5) -* [6. Ключевые понятия: факт/измерение, зерно, SK vs BK, SCD](#6) -* [7. Выбор подхода: дерево решений](#7) -* [8. Эволюция схемы и эксплуатации](#8) -* [9. MVP учебного проекта](#9) -* [10. Заключение](#10) - ---- - -## 1. Введение: зачем слои и почему не «всё в одну таблицу» - -**Коротко**: OLTP vs OLAP, управляемость, прозрачность, стоимость. - -**Заглушки для текста**: - -* Что такое слои и какую проблему решают. -* Почему «одна большая таблица» ломается на истории и изменениях. -* 3–4 тезиса о выгодах послойной архитектуры. - ---- - -## 2. Учебный домен/пример (интернет-магазин) - -**Описание**: используем один домен сквозь статью: клиенты, товары, заказы, позиции заказа, цены, акции. - -**Диаграмма ER (эскиз)**: - -```mermaid -erDiagram - CUSTOMER ||--o{ ORDER : places - ORDER ||--|{ ORDER_ITEM : contains - PRODUCT ||--o{ ORDER_ITEM : referenced - PRODUCT ||--o{ PRICE : has - PROMO ||--o{ ORDER_ITEM : applied - CUSTOMER { - int customer_id PK - string email - string phone - } - PRODUCT { - int product_id PK - string name - } - ORDER { - int order_id PK - date order_date - int customer_id FK - } - ORDER_ITEM { - int order_item_id PK - int order_id FK - int product_id FK - int qty - numeric price_at_sale - } - PRICE { - int product_id FK - date valid_from - date valid_to - numeric price - } - PROMO { - int promo_id PK - string code - } -``` - -**Заглушки**: 2–3 абзаца с пояснениями domain-гранулярности и бизнес-ключей (BK). - ---- - -## 3. Типичная структура слоёв (STG → ODS → DDS → DM) - -**Картинка-конвейер (эскиз)**: - -```mermaid -flowchart TD - subgraph Sources[Источники] - A[CRM] --> STG - B[Billing] --> STG - C[E-comm] --> STG - end - STG[STG
Staging / Bronze] --> ODS[ODS
Operational / Silver] - ODS --> DDS[DDS
Integrated / Conformed] - DDS --> DM[DM
Data Marts / Gold] - DM --> BI[BI / Отчёты / Дашборды] -``` - -**Заглушки**: - -* Соответствие Bronze/Silver/Gold. -* Что происходит на каждом переходе в 1–2 фразы. - ---- - -## 4. Слои по отдельности - -### 4.1 STG (Staging/Bronze) - -**Коротко**: «как пришло». Идемпотентность, дедупликация, неизменяемость/переигрузка. - -**TODO**: список «что можно» / «что нельзя»; форматы; контроль качества на входе. - -### 4.2 ODS (Operational Data Store/Silver) - -**Коротко**: чистка и выравнивание типов, базовая унификация кодов, ещё без тяжёлой бизнес-логики. - -**TODO**: правила именования, ключи, простая история. - -### 4.3 DDS (Integrated/Conformed Layer) - -**Коротко**: интеграция источников, общие справочники, SK/BK, SCD. Здесь уже начинаются модели данных. Какие модели испольуют. - -**TODO**: где хранить историю, антидубли, конформные измерения. - -### 4.4 DM (Data Marts/Gold) - -**Коротко**: модели под задачи BI (звезда/снежинка). Агрегаты, материализации. - -**TODO**: границы ответственности витрин. - ---- - -## 5. Модели данных для DDS/DM: 3NF, Звезда/Снежинка, Data Vault, Anchor - -### 5.1 3NF (по Инмону, 3-я нормальная форма) - -**Идея**: целостная интегрированная модель предприятия. - -**Мини-эскиз (ER, нормализовано)**: - -```mermaid -erDiagram - CUSTOMER ||--o{ ORDER : places - ORDER ||--|{ ORDER_ITEM : contains - PRODUCT ||--o{ ORDER_ITEM : referenced - CATEGORY ||--o{ PRODUCT : classifies - PRICE ||--o{ PRODUCT : defines -``` - -**TODO**: плюсы/минусы, когда выбирать. - -### 5.2 Звезда/Снежинка (по Кимбаллу) - -**Идея**: простые и быстрые аналитические запросы.  -Упомянуть, что самая часто испольуемая модель. - -**Эскиз звезды: факт + измерения**: - -```mermaid -flowchart LR - F[fact_orders
order_id, date_key, customer_key, product_key, qty, amount] - D1[dim_date] --> F - D2[dim_customer] --> F - D3[dim_product] --> F - D4[dim_store] --> F -``` - -**Эскиз снежинки (нормализация измерения продукта)**: - -```mermaid -graph LR - D3[dim_product] --> C[dim_category] -``` - -**TODO**: зерно факта, типы измерений, агрегаты. - -### 5.3 Data Vault 2.0 (Hub–Link–Satellite) - -**Идея**: масштабируемая интеграция многоисточниковых данных с полной историей. - -**Эскиз DV (упорядоченная колонками)**: - -```mermaid -flowchart LR - %% Hubs (слева) - HC[Hub_Customer] - HO[Hub_Order] - HP[Hub_Product] - - %% Links (центр) - LOC[Link_OrderCustomer] - LOP[Link_OrderProduct] - - %% Satellites (справа) - SC[SAT_Customer] - SO[SAT_Order] - SP[SAT_Product] - - %% Связи к сателлитам - HC --> SC - HO --> SO - HP --> SP - - %% Связи между хабами и линками - HC --> LOC - HO --> LOC - HO --> LOP - HP --> LOP -``` - -**TODO**: Raw Vault vs Business Vault, плюс/минус. -На каких слоях используем, зачем там оно нам. - -Схема часто используется. Пишем, почему. - -### 5.4 Anchor Modeling (Анкерное моделирование) - -**Идея**: эволюционируемость атрибутов с версионированием на уровне «якорей/атрибутов/узлов». - -**Эскиз (упрощённый)**: - -```mermaid -flowchart LR - AC[Anchor CUSTOMER] - KC[Knot CUSTOMER_ID] - AC --> KC - AC --> AN[Attr NAME] - AC --> AE[Attr EMAIL] - AN --> NV[Name values history] - AE --> EV[Email values history] -``` - -**TODO**: где уместно, порог входа. - -**TODO**: где уместно, порог входа. - -Редко используется. Сложна для людей и для машин. Обосновываем. - ---- - -## 6. Ключевые понятия (минимум для практики) - -* **Факты (Facts)** и **Измерения (Dimensions)**; **зерно (grain)** факта. -* **Натуральные ключи (BK)** и **суррогатные ключи (SK)**. -* **SCD (Slowly Changing Dimensions)**: типы 1 / 2 / 4 / 6. -* **Bridge/Junk dimensions**, календарь, валюта, часовой пояс. -* **Поздно прибывающие события (late arriving)**. - -**Эскиз SCD‑истории (Type 2) как лента времени**: - -```mermaid -gantt - dateFormat YYYY-MM-DD - title SCD Type 2: dim_customer.name - section Customer 42 - Version_1 :active, v1, 2023-01-01, 2023-06-14 - Version_2 : v2, 2023-06-15, 2024-02-28 - Version_3 : v3, 2024-03-01, 2025-10-26 -``` - -**TODO**: короткие примеры для Type 1/2/4/6. - ---- - -## 7. Эволюция схемы и эксплуатационные практики - -* Совместимость назад/вперёд, view‑based миграции. -* Идемпотентные пайплайны, дедупликация, инкрементальные загрузки (CDC). -* Data Quality: уникальность, ссылочная целостность, распределения, «contracts». -* Каталог/линейка (Data Catalog / Lineage), словарь данных (Business Glossary), владение. - -**TODO**: чек-лист из 8–10 пунктов. - ---- -## 10. Заключение - -**Заглушки**: повторить ключевые тезисы, дать ссылки на дополнительные темы: CDC, оркестрация, тестирование данных, наблюдаемость. - ---- - -## Примечания к иллюстрациям - -* Диаграммы — **эскизы**: заменить/уточнить, когда будет готов текст. -* При необходимости добавить отдельные рисунки: «что можно/нельзя в слоях», SCD типы на одном полотне, пример late arriving events. diff --git a/dwh-modeling/dwh-modeling-ds.md b/dwh-modeling/dwh-modeling-ds.md deleted file mode 100644 index b910b01..0000000 --- a/dwh-modeling/dwh-modeling-ds.md +++ /dev/null @@ -1,549 +0,0 @@ -Что нас здесь ждет - -* **Уже умеете:** SQL-основы (SELECT/JOIN/GROUP BY), простые агрегаты. -* **Узнаете:** слои (STG/ODS/DDS/DM), модели (3NF/Star/DV/Anchor), SCD и суррогатные ключи. -* **Не рассматриваем здесь:** физический дизайн, производительность, партиционирование, распределённые кластеры — это отдельная тема. - -# **Структура статьи про хранилище данных ** - -1. Введение. Проблема аналитики в OLTP -2. Учебный пример. Интернет-магазин -3. Архитектура. Зачем слои? -4. Путешествие данных. STG→ODS→DDS→DM -5. Базовые понятия. Факты, Измерения, SCD -6. Модели данных. 3NF, DV, Звезда -7. Практикум. Собираем витрину -8. Выбор моделию Дерево решений -9. Эксплуатация. Качество и эволюция -10. Заключение - ---- - -# **1. Введение: Аналитика — это не оперативный учет** - -**OLTP (оперативный учёт)**: CRM, заказы, склад. -**DWH (аналитическое хранилище)**: единая модель для анализа. - -Проблема: в OLTP для исторической аналитики — сложные JOIN, тяжёлые агрегации, нестабильная производительность. - -**Особенности DWH**: - -* Слоистая архитектура -* Оптимизированные под аналитику модели - -**Ключевые тезисы**: - -* OLTP vs OLAP: транзакции против анализа -* Почему «одна большая таблица» не работает на истории -* 3 преимущества слоёв: управляемость, производительность, прозрачность - ---- - -# **2. Учебный пример: интернет-магазин** - -ER-диаграмма сущностей источника (упрощённо): - -```mermaid -erDiagram - CUSTOMER ||--o{ ORDER : places - ORDER ||--|{ ORDER_ITEM : contains - PRODUCT ||--o{ ORDER_ITEM : referenced - PRODUCT ||--o{ PRICE : has - PROMO ||--o{ ORDER_ITEM : applied - CUSTOMER { - int customer_id PK - string email - string phone - } - PRODUCT { - int product_id PK - string name - } - ORDER { - int order_id PK - date order_date - int customer_id FK - } - ORDER_ITEM { - int order_item_id PK - int order_id FK - int product_id FK - int qty - numeric price_at_sale - } - PRICE { - int product_id FK - date valid_from - date valid_to - numeric price - } - PROMO { - int promo_id PK - string code - } -``` - -Описание примера текстом - ---- - -# **3. Архитектура хранилища: зачем делить на слои?** - -```mermaid -flowchart TD - subgraph Sources[Источники OLTP] - A[CRM] - B[Заказы] - C[Склад] - end - - A --> STG - B --> STG - C --> STG - - subgraph STG[STG - Сырые данные] - D[Таблицы-клоны
сырые данные] - end - - STG --> ODS - - subgraph ODS[ODS - Очищенные данные] - E[Стандартизированные
типы и форматы] - end - - ODS --> DDS - - subgraph DDS[DDS - Интегрированная модель] - F[Бизнес-сущности
SCD, интеграция] - end - - DDS --> DM - - subgraph DM[DM - Витрины для аналитики] - G[Звезда/снежинка
агрегаты] - end - - DM --> BI[BI-системы
и отчеты] -``` - ---- - -## **4. Путешествие данных по слоям** - -```mermaid -flowchart LR - subgraph STG[STG - Сырье] - A[raw_orders.json] - B[raw_customers.csv] - C[Формат как в источнике] - end - - subgraph ODS[ODS - Очистка] - D[stg_orders] - E[stg_customers] - F[Типизация, валидация] - end - - subgraph DDS[DDS - Интеграция] - G[dim_customer
SCD Type 2] - H[fact_orders
с суррогатными ключами] - end - - subgraph DM[DM - Готовые решения] - I[mart_sales
агрегированные данные] - J[mart_customer_360
обзор по клиентам] - end - - STG --> ODS - ODS --> DDS - DDS --> DM -``` - -STG (Staging/Bronze) - -Коротко: «как пришло». Идемпотентность, дедупликация, неизменяемость/переигрузка. - -ODS (Operational Data Store/Silver) - -Коротко: чистка и выравнивание типов, базовая унификация кодов, ещё без тяжёлой бизнес-логики. - -DDS (Integrated/Conformed) - -Коротко: интеграция источников, общие справочники, SK/BK, SCD. Здесь живут модели данных (3NF/DV/Anchor/Star). - -DM (Data Marts/Gold) - -Коротко: модели под задачи BI (звезда/снежинка). Агрегаты, материализации. - -* **STG (Bronze):** как пришло; неизменяемо/переигрузка; идемпотентность; дедуп по `(BK, load_ts)`; только тех. обогащения (например, `_ingest_id`). -* **ODS (Silver):** типизация; базовая очистка и стандартные коды; **без** тяжёлой бизнес-логики; стабильные схемы/имена. -* **DDS (Conformed/Core):** интеграция источников; единая терминология; SK/BK; SCD; здесь живут модели (3NF/Star/DV/Anchor). -* **DM (Gold):** под конкретные вопросы BI/продукта; агрегаты/материализации; доступные метрики и измерения. - -Нейминг-гайд (пример) - -* `stg.*` — как в источнике, добавочные тех. поля: `_ingest_id`, `_load_ts`. -* `ods.*` — очищенные «плоские» таблицы, стаб. схемы. -* `dds.dim_*`, `dds.fact_*` — интегрированная модель. -* `dm.mart_*` — витрины/представления. - ---- - -## **5. Базовые понятия: Факты, Измерения, Ключи** - -```mermaid -erDiagram - dim_date ||--o{ fact_sales : "дата" - dim_customer ||--o{ fact_sales : "клиент" - dim_product ||--o{ fact_sales : "товар" - - dim_customer { - bigint customer_sk PK - varchar customer_bk - varchar customer_name - varchar email - date valid_from - date valid_to - boolean is_current - } - - fact_sales { - bigint sale_id PK - bigint customer_sk FK - bigint product_sk FK - date date_sk FK - int quantity - decimal amount - } -``` - -Что из базвой модели данных - -**SCD Type 2 - Визуализация истории**: - -```mermaid -gantt - title SCD Type 2: История изменений клиента (ID = 123) - dateFormat YYYY-MM-DD - axisFormat %Y-%m - - section Москва, premium@email.com - Версия 1 :active, 2023-01-01, 2023-05-15 - - section Москва, new_premium@email.com - Версия 2 :active, 2023-05-16, 2023-09-30 - - section Санкт-Петербург, new_premium@email.com - Версия 3 :active, 2023-10-01, 2024-12-31 -``` -в fact берём версию dim_customer по дате факта (между valid_from и valid_to) - -Краткое описание текстом. Указание, что подробно про scd можно почитать в соседней статье SCD.md - ---- - -## **6. Модели данных для DDS** - -### 3NF (третья нормальная форма) - -Классическая нормализованная модель, сильная целостность и интеграция, но SQL для аналитики сложнее. - -### Снежинка (Snowflake) - -Нормализованные измерения поверх звезды — компромисс между читаемостью и дублированием. - -### Звезда (Star Schema) - -Факт + денормализованные измерения — просто и быстро для BI/SQL. - -### **Data Vault 2.0**: - -```mermaid -erDiagram - hub_customer ||--o{ sat_customer_info : "хаб" - hub_order ||--o{ sat_order_details : "хаб" - hub_product ||--o{ sat_product_info : "хаб" - - hub_customer ||--o{ link_order_customer : "участвует" - hub_order ||--o{ link_order_customer : "включает" - - hub_order ||--o{ link_order_product : "содержит" - hub_product ||--o{ link_order_product : "входит в" - - hub_customer { - string customer_hash_key PK - string customer_id BK - datetime load_dttm - } - - sat_customer_info { - string customer_hash_key PK,FK - datetime load_dttm PK - string customer_name - string email - string phone - } - - link_order_customer { - string order_customer_hash_key PK - string order_hash_key FK - string customer_hash_key FK - datetime load_dttm - } -``` - -Коротко: хабы (BK), линки (связи), сателлиты (история атрибутов). Этот раздел обзорный. - -Упомянуть про DV 1 - -### Anchor Modeling (анкерное моделирование) - -Атомарная декомпозиция сущностей и атрибутов, гибкая эволюция схемы; высокая гранулярность усложняет чтение. - -> **Сравнение (интуитивно):** Звезда — проще/быстрее для BI; 3NF — целостность и интеграция; DV/Anchor — масштабируемая интеграция из многих источников и «история по умолчанию», но сложнее читать и писать. - -**Сравнение моделей**: - -```mermaid -quadrantChart - title Сравнение моделей данных по сложности и гибкости - x-axis "Низкая сложность" --> "Высокая сложность" - y-axis "Низкая гибкость" --> "Высокая гибкость" - "Звезда": [0.2, 0.3] - "3NF": [0.6, 0.5] - "Data Vault": [0.8, 0.8] - "Anchor": [0.9, 0.9] -``` -Рассказать, что выбор модели для данных далеко не всегда однозначен, и является компромисснным. - -3NF - преимущества и недостатки -Снежинка - преимущества и недостатки -DV -Anchor Modeling - ---- - -#### **7. Практикум: собираем витрину** - -Раздел мне не нравится, надо бы переработать. - -```mermaid -flowchart TD - A[Источники] --> STG - STG[STG: сырые заказы, товары] --> ODS - ODS[ODS: очищенные данные] --> DDS - - subgraph DDS[DDS: интегрированная модель] - B[dim_customer
SCD Type 2] - C[dim_product] - D[dim_date] - E[fact_sales] - end - - DDS --> F{Сборка витрины} - - F --> G[mart_daily_sales] - F --> H[mart_customer_lifetime] - - G --> I[Дашборд продаж] - H --> J[Отчет по клиентам] -``` - -**Пример SQL для витрины**: -```sql --- Витрина ежедневных продаж -CREATE TABLE mart_daily_sales AS -SELECT - d.date, - p.product_name, - c.customer_segment, - SUM(f.quantity) as total_quantity, - SUM(f.amount) as total_amount -FROM fact_sales f -JOIN dim_date d ON f.date_key = d.date_key -JOIN dim_product p ON f.product_key = p.product_key -JOIN dim_customer c ON f.customer_key = c.customer_key -WHERE c.is_current = true -GROUP BY d.date, p.product_name, c.customer_segment; -``` - ---- - -#### **9. Эксплуатация: качество и эволюция** - -```mermaid -graph TB - A[Данные] --> B{Контроль качества} - - B --> C[Проверка уникальности] - B --> D[Проверка полноты] - B --> E[Валидация форматов] - B --> F[Свежесть данных] - - C --> G[✅ Успех] - D --> G - E --> G - F --> G - - C --> H[❌ Ошибка] - D --> H - E --> H - F --> H - - G --> I[Загрузка в слой] - H --> J[Оповещение
и остановка] -``` - ---- - -#### **10. Заключение: главное — понимать "почему"** - -```mermaid -mindmap - root((Хранилище данных)) - Архитектура - Слои STG→ODS→DDS→DM - Разделение ответственности - Управляемость изменений - Модели данных - 3NF: Целостность - Data Vault: Масштабируемость - Звезда: Производительность - Ключевые понятия - Факты и измерения - Суррогатные ключи - SCD Type 2 - Практика - Понимать бизнес-задачу - Выбирать подходящую модель - Строить итеративно -``` - ---- - -## **10. Заключение: главное — понимать «почему»** - -Ключевые идеи: разделение на слои (STG → ODS → DDS → DM), разные модели для разных задач (3NF, Star, DV, Anchor), факты/измерения/SCD, итеративная сборка витрин под конкретные вопросы бизнеса. - -# Приложения - -### 2) Мини-глоссарий RU/EN (по 1–2 строки) - -* **Слой (Layer)** — логический уровень в DWH: STG/ODS/DDS/DM. -* **Витрина (Data Mart)** — предметно-ориентированный набор таблиц/представлений для конкретной аналитики. -* **Факт (Fact)** — таблица событий/измерений величин (кол-во, сумма). -* **Измерение (Dimension)** — справочник контекста фактов (клиенты, товары, даты). -* **Суррогатный ключ (Surrogate Key, SK)** — искусственный технический ключ (int/bigint). -* **Бизнес-ключ (Business Key, BK)** — естественный ключ из источника (например, `customer_id`). -* **SCD (Slowly Changing Dimension)** — подход к хранению истории атрибутов измерения. -* **CDC (Change Data Capture)** — техника инкрементальной загрузки изменений. -* **Conformed Dimension** — «конформное» измерение, общее для нескольких витрин. - -### 3) Отображение синонимов слоёв - -* **STG (Bronze)** → **ODS (Silver)** → **DDS (Conformed/Core)** → **DM (Gold)**. - -### 4) «Правила слоя» — короткие чек-листы - - - -### 5) Антипаттерны (короткий бокс) - -* «Одна огромная историческая таблица» → медленные запросы, нет истории атрибутов. -* «Смешали STG и ODS» → потеря трассировки ошибок и инцидентов качества. -* «Факт с текстовыми атрибутами без причин» → раздутая таблица и неявные бизнес-правила. -* «SCD без BK» → история «плывёт», не привязана к бизнес-идентификатору. - - - - -### 10) «Зачем разные модели» (без выбора) - -* **Star (звезда):** быстро писать отчёты, учим новичков на ней. -* **3NF:** лучшая консистентность/интеграция понятий, тяжелее для BI. -* **Data Vault:** масштабируемая интеграция множества источников + «история по умолчанию». -* **Anchor:** гибкая эволюция схемы, максимальная атомарность, цена — сложность. - -### 11) Что почитать дальше - -* **Kimball, The Data Warehouse Toolkit** — модели «звезды», SCD. -* **Inmon, Building the Data Warehouse** — корпоративный DWH и нормализация. -* **Linstedt & Olschimke, The Data Vault 2.0** — практический DV. -* **Anchor Modeling** — официальный сайт/документация по Anchor. - ---- - -## ЧАСТЬ C. Мини-датасет (для примеров в статье) - -> Опционально приложить к репозиторию/приложению статьи. - -**customers.csv** - -``` -customer_id,email,phone,city -101,a@ex.com,700,Москва -101,b@ex.com,700,Москва -102,c@ex.com,701,СПб -``` - -**orders.csv** - -``` -order_id,order_date,customer_id -5001,2024-01-10,101 -5002,2024-02-05,102 -``` - -**order_items.csv** - -``` -order_item_id,order_id,product_id,qty,price_at_sale -1,5001,9001,2,100.00 -2,5001,9002,1,50.00 -3,5002,9001,1,100.00 -``` - -**products.csv** - -``` -product_id,name -9001,Phone -9002,Case -``` - -**prices.csv** - -``` -product_id,valid_from,valid_to,price -9001,2023-12-01,2024-01-31,100 -9001,2024-02-01,2999-12-31,110 -``` - ---- - -## ЧАСТЬ D. DDL-скелеты (минимально) - -```sql --- DDS: измерение клиента (Type 2) -CREATE TABLE dds.dim_customer ( - customer_sk BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, - customer_bk VARCHAR NOT NULL, - email VARCHAR, - phone VARCHAR, - city VARCHAR, - valid_from DATE NOT NULL, - valid_to DATE, - is_current BOOLEAN NOT NULL DEFAULT TRUE -); - --- DDS: факт продаж (гранулярность: строка заказа) -CREATE TABLE dds.fact_sales ( - sale_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, - customer_sk BIGINT NOT NULL, - product_sk BIGINT NOT NULL, - date_sk INT NOT NULL, - quantity INT NOT NULL, - amount DECIMAL(18,2) NOT NULL -); -``` - diff --git a/dwh-modeling/dwh-modeling-plan3.md b/dwh-modeling/dwh-modeling-plan3.md deleted file mode 100644 index eb2a4f6..0000000 --- a/dwh-modeling/dwh-modeling-plan3.md +++ /dev/null @@ -1,570 +0,0 @@ -# Модели данных и слои DWH (для менти) - -**Цель и аудитория:** эта статья для начинающих аналитиков/инженеров данных, которые уже умеют базовый SQL (SELECT/JOIN/GROUP BY/WHERE) и переходят к моделированию данных и архитектуре хранилища (Data Warehouse, DWH). Здесь даём общее представление: **зачем слои**, **что такое модели**, **чем они отличаются**, где обычно живут **факты/измерения/SCD**. **Выбор модели** в продакшен за вас делать не будем — на этом этапе важно понять, *зачем разные модели существуют* и *какие задачи они решают*. - ---- - -## ЧАСТЬ A. Исходный черновик статьи (переделан в чистовик с лёгкой правкой опечаток) - -Ниже — аккуратно отредактированная версия вашего плана с диаграммами Mermaid. Сохранили исходную структуру и формулировки, поправили опечатки и выровняли стиль именования. - ---- - -# **Структура статьи про хранилище данных** - -1. Введение. Проблема аналитики в OLTP -2. Учебный пример. Интернет-магазин -3. Архитектура. Зачем слои? -4. Путешествие данных. STG → ODS → DDS → DM -5. Базовые понятия. Факты, Измерения, SCD -6. Модели данных. 3NF, Data Vault, Звезда -7. Практикум. Собираем витрину -8. Зачем разные модели (демо-«дерево решений») -9. Эксплуатация. Качество и эволюция -10. Заключение - -> Примечание про Mermaid: диаграммы `mindmap` и `quadrantChart` поддерживаются не всеми рендерами. Если планируете публикацию на площадке со строгим Markdown (например, Habr), оставьте текстовую альтернативу. - ---- - -## **1. Введение: аналитика — это не оперативный учёт** - -**OLTP (оперативный учёт)**: CRM, заказы, склад. -**DWH (аналитическое хранилище)**: единая модель для анализа. - -Проблема: в OLTP для исторической аналитики — сложные JOIN, тяжёлые агрегации, нестабильная производительность. - -**Особенности DWH**: - -* Слоистая архитектура -* Оптимизированные под аналитику модели - -**Ключевые тезисы**: - -* OLTP vs OLAP: транзакции против анализа -* Почему «одна большая таблица» не работает на истории -* 3 преимущества слоёв: управляемость, производительность, прозрачность - ---- - -## **2. Учебный пример: интернет-магазин** - -ER-диаграмма сущностей источника (упрощённо): - -```mermaid -erDiagram - CUSTOMER ||--o{ ORDER : places - ORDER ||--|{ ORDER_ITEM : contains - PRODUCT ||--o{ ORDER_ITEM : referenced - PRODUCT ||--o{ PRICE : has - PROMO ||--o{ ORDER_ITEM : applied - CUSTOMER { - int customer_id PK - string email - string phone - } - PRODUCT { - int product_id PK - string name - } - ORDER { - int order_id PK - date order_date - int customer_id FK - } - ORDER_ITEM { - int order_item_id PK - int order_id FK - int product_id FK - int qty - numeric price_at_sale - } - PRICE { - int product_id FK - date valid_from - date valid_to - numeric price - } - PROMO { - int promo_id PK - string code - } -``` - ---- - -## **3. Архитектура хранилища: зачем делить на слои?** - -```mermaid -flowchart TD - subgraph Sources[Источники OLTP] - A[CRM] - B[Заказы] - C[Склад] - end - - A --> STG - B --> STG - C --> STG - - subgraph STG[STG (Bronze) — сырые данные] - D[Таблицы-клоны \n неизменяемые/переигрузка] - end - - STG --> ODS - - subgraph ODS[ODS (Silver) — очищенные] - E[Типизация, валидация, \n стандартизация кодов] - end - - ODS --> DDS - - subgraph DDS[DDS — интегрированная модель] - F[Бизнес-сущности, SK/BK, SCD] - end - - DDS --> DM - - subgraph DM[DM (Gold) — витрины] - G[Звезда/Снежинка, агрегаты] - end - - DM --> BI[BI/Отчёты] -``` - ---- - -## **4. Путешествие данных по слоям** - -```mermaid -flowchart LR - subgraph STG[STG — сырьё] - A[raw_orders.json] - B[raw_customers.csv] - C[Формат как в источнике] - end - - subgraph ODS[ODS — очистка] - D[stg_orders] - E[stg_customers] - F[Типизация, валидация] - end - - subgraph DDS[DDS — интеграция] - G[dim_customer — SCD2] - H[fact_orders — с суррогатными ключами] - end - - subgraph DM[DM — готовые решения] - I[mart_sales — агрегаты] - J[mart_customer_360] - end - - STG --> ODS - ODS --> DDS - DDS --> DM -``` - -### 4.1 STG (Staging/Bronze) - -Коротко: «как пришло». Идемпотентность, дедупликация, неизменяемость/переигрузка. - -### 4.2 ODS (Operational Data Store/Silver) - -Коротко: чистка и выравнивание типов, базовая унификация кодов, ещё без тяжёлой бизнес-логики. - -### 4.3 DDS (Integrated/Conformed) - -Коротко: интеграция источников, общие справочники, SK/BK, SCD. Здесь живут модели данных (3NF/DV/Anchor/Star). - -### 4.4 DM (Data Marts/Gold) - -Коротко: модели под задачи BI (звезда/снежинка). Агрегаты, материализации. - ---- - -## **5. Базовые понятия: факты, измерения, ключи** - -```mermaid -erDiagram - dim_date ||--o{ fact_sales : "дата" - dim_customer ||--o{ fact_sales : "клиент" - dim_product ||--o{ fact_sales : "товар" - - dim_customer { - bigint customer_sk PK - varchar customer_bk - varchar customer_name - varchar email - date valid_from - date valid_to - boolean is_current - } - - fact_sales { - bigint sale_id PK - bigint customer_sk FK - bigint product_sk FK - int date_sk FK - int quantity - decimal amount - } -``` - -**SCD Type 2 — визуализация истории:** - -```mermaid -gantt - title SCD Type 2: История изменений клиента (ID = 123) - dateFormat YYYY-MM-DD - axisFormat %Y-%m - - section Москва, premium@email.com - Версия 1 :active, 2023-01-01, 2023-05-15 - - section Москва, new_premium@email.com - Версия 2 :active, 2023-05-16, 2023-09-30 - - section Санкт-Петербург, new_premium@email.com - Версия 3 :active, 2023-10-01, 2024-12-31 -``` - ---- - -## **6. Модели данных для DDS** - -### 3NF (третья нормальная форма) - -Классическая нормализованная модель, сильная целостность и интеграция, но SQL для аналитики сложнее. - -### Снежинка (Snowflake) - -Нормализованные измерения поверх звезды — компромисс между читаемостью и дублированием. - -### Звезда (Star Schema) - -Факт + денормализованные измерения — просто и быстро для BI/SQL. - -### **Data Vault 2.0** - -```mermaid -erDiagram - HUB_CUSTOMER ||--o{ SAT_CUSTOMER : has_history - HUB_ORDER ||--o{ SAT_ORDER : has_history - HUB_PRODUCT ||--o{ SAT_PRODUCT : has_history - - HUB_CUSTOMER ||--o{ LNK_ORDER_CUSTOMER : participates - HUB_ORDER ||--o{ LNK_ORDER_CUSTOMER : includes - - HUB_ORDER ||--o{ LNK_ORDER_PRODUCT : contains - HUB_PRODUCT ||--o{ LNK_ORDER_PRODUCT : involved - - HUB_CUSTOMER { - string customer_hk PK - string customer_bk - datetime load_dts - string src - } - - LNK_ORDER_PRODUCT { - string order_product_hk PK - string order_hk FK - string product_hk FK - datetime load_dts - string src - } - - SAT_CUSTOMER { - string customer_hk PK,FK - datetime load_dts PK - string email - string phone - string city - hashdiff hash - } -``` - -Коротко: хабы (BK), линки (связи), сателлиты (история атрибутов). Этот раздел обзорный. - -### Anchor Modeling (анкерное моделирование) - -Атомарная декомпозиция сущностей и атрибутов, гибкая эволюция схемы; высокая гранулярность усложняет чтение. - -> **Сравнение (интуитивно):** Звезда — проще/быстрее для BI; 3NF — целостность и интеграция; DV/Anchor — масштабируемая интеграция из многих источников и «история по умолчанию», но сложнее читать и писать. - ---- - -## **7. Практикум: собираем витрину** - -```mermaid -flowchart TD - A[Источники] --> STG - STG[STG: сырые заказы, товары] --> ODS - ODS[ODS: очищенные данные] --> DDS - - subgraph DDS[DDS: интегрированная модель] - B[dim_customer (SCD2)] - C[dim_product] - D[dim_date] - E[fact_sales] - end - - DDS --> F{Сборка витрины} - - F --> G[mart_daily_sales] - F --> H[mart_customer_lifetime] - - G --> I[Дашборд продаж] - H --> J[Отчёт по клиентам] -``` - -**Пример SQL для витрины:** - -```sql --- Витрина ежедневных продаж (пример) -CREATE TABLE mart_daily_sales AS -SELECT - d.date, - p.product_name, - c.customer_segment, - SUM(f.quantity) AS total_quantity, - SUM(f.amount) AS total_amount -FROM fact_sales f -JOIN dim_date d ON f.date_sk = d.date_sk -JOIN dim_product p ON f.product_sk = p.product_sk -JOIN dim_customer c ON f.customer_sk = c.customer_sk AND c.is_current = TRUE -GROUP BY d.date, p.product_name, c.customer_segment; -``` - ---- - -## **9. Эксплуатация: качество и эволюция** - -```mermaid -graph TB - A[Данные] --> B{Контроль качества} - B --> C[Проверка уникальности] - B --> D[Проверка полноты] - B --> E[Валидация форматов] - B --> F[Свежесть данных] - C --> G[✅ Успех] - D --> G - E --> G - F --> G - C --> H[❌ Ошибка] - D --> H - E --> H - F --> H - G --> I[Загрузка в слой] - H --> J[Оповещение и остановка] -``` - ---- - -## **10. Заключение: главное — понимать «почему»** - -Ключевые идеи: разделение на слои (STG → ODS → DDS → DM), разные модели для разных задач (3NF, Star, DV, Anchor), факты/измерения/SCD, итеративная сборка витрин под конкретные вопросы бизнеса. - ---- - -## ЧАСТЬ B. Наши предложения к статье (что усилено и что добавить) - -Ниже — блоки, которые можно встроить в соответствующие разделы или вынести в отдельные боксы/врезки. - -### 1) Рамочный ввод «что вы знаете / что узнаете / чего не будет» - -* **Уже умеете:** SQL-основы (SELECT/JOIN/GROUP BY), простые агрегаты. -* **Узнаете:** слои (STG/ODS/DDS/DM), модели (3NF/Star/DV/Anchor), SCD и суррогатные ключи. -* **Не рассматриваем здесь:** физический дизайн, производительность, партиционирование, распределённые кластеры — это отдельная тема. - -### 2) Мини-глоссарий RU/EN (по 1–2 строки) - -* **Слой (Layer)** — логический уровень в DWH: STG/ODS/DDS/DM. -* **Витрина (Data Mart)** — предметно-ориентированный набор таблиц/представлений для конкретной аналитики. -* **Факт (Fact)** — таблица событий/измерений величин (кол-во, сумма). -* **Измерение (Dimension)** — справочник контекста фактов (клиенты, товары, даты). -* **Суррогатный ключ (Surrogate Key, SK)** — искусственный технический ключ (int/bigint). -* **Бизнес-ключ (Business Key, BK)** — естественный ключ из источника (например, `customer_id`). -* **SCD (Slowly Changing Dimension)** — подход к хранению истории атрибутов измерения. -* **CDC (Change Data Capture)** — техника инкрементальной загрузки изменений. -* **Conformed Dimension** — «конформное» измерение, общее для нескольких витрин. - -### 3) Отображение синонимов слоёв - -* **STG (Bronze)** → **ODS (Silver)** → **DDS (Conformed/Core)** → **DM (Gold)**. - -### 4) «Правила слоя» — короткие чек-листы - -* **STG (Bronze):** как пришло; неизменяемо/переигрузка; идемпотентность; дедуп по `(BK, load_ts)`; только тех. обогащения (например, `_ingest_id`). -* **ODS (Silver):** типизация; базовая очистка и стандартные коды; **без** тяжёлой бизнес-логики; стабильные схемы/имена. -* **DDS (Conformed/Core):** интеграция источников; единая терминология; SK/BK; SCD; здесь живут модели (3NF/Star/DV/Anchor). -* **DM (Gold):** под конкретные вопросы BI/продукта; агрегаты/материализации; доступные метрики и измерения. - -### 5) Антипаттерны (короткий бокс) - -* «Одна огромная историческая таблица» → медленные запросы, нет истории атрибутов. -* «Смешали STG и ODS» → потеря трассировки ошибок и инцидентов качества. -* «Факт с текстовыми атрибутами без причин» → раздутая таблица и неявные бизнес-правила. -* «SCD без BK» → история «плывёт», не привязана к бизнес-идентификатору. - -### 6) SCD2: рецепт джойна «по интервалу» (шпаргалка) - -```sql --- Привязка факта к актуальной версии измерения (Type 2) -SELECT f.*, d.customer_sk -FROM fact_sales f -JOIN dim_customer d - ON d.customer_bk = f.customer_bk -- совпадение BK - AND f.event_date >= d.valid_from - AND f.event_date < COALESCE(d.valid_to, DATE '2999-12-31'); -``` - -### 7) Мини-практикум (сквозной, короткий) - -1. Показать джойн факта к SCD2-измерению (по примеру выше). -2. Собрать `mart_daily_sales` (у вас уже есть SQL). -3. Пара проверок качества (см. ниже). - -### 8) Качество данных: минимальные метрики + однострочники - -* **Freshness (свежесть):** `MAX(event_time)` против «сейчас». -* **Completeness (полнота):** доля NULL по важным столбцам. -* **Consistency (согласованность):** факт без соответствия в измерении (нарушение покрытии ссылок). -* **Uniqueness (уникальность):** уникальность BK в справочнике. - -```sql --- Примеры «однострочников» --- Freshness -SELECT NOW() - MAX(event_time) AS lag FROM ods.order; - --- Uniqueness BK -SELECT customer_bk, COUNT(*) -FROM dds.dim_customer -GROUP BY customer_bk -HAVING COUNT(*) > 1; - --- Orphan facts (без покрытия измерения) -SELECT COUNT(*) -FROM dds.fact_sales f -LEFT JOIN dds.dim_customer d ON f.customer_sk = d.customer_sk -WHERE d.customer_sk IS NULL; -``` - -### 9) Нейминг-гайд (пример) - -* `stg.*` — как в источнике, добавочные тех. поля: `_ingest_id`, `_load_ts`. -* `ods.*` — очищенные «плоские» таблицы, стаб. схемы. -* `dds.dim_*`, `dds.fact_*` — интегрированная модель. -* `dm.mart_*` — витрины/представления. - -### 10) «Зачем разные модели» (без выбора) - -* **Star (звезда):** быстро писать отчёты, учим новичков на ней. -* **3NF:** лучшая консистентность/интеграция понятий, тяжелее для BI. -* **Data Vault:** масштабируемая интеграция множества источников + «история по умолчанию». -* **Anchor:** гибкая эволюция схемы, максимальная атомарность, цена — сложность. - -### 11) Что почитать дальше - -* **Kimball, The Data Warehouse Toolkit** — модели «звезды», SCD. -* **Inmon, Building the Data Warehouse** — корпоративный DWH и нормализация. -* **Linstedt & Olschimke, The Data Vault 2.0** — практический DV. -* **Anchor Modeling** — официальный сайт/документация по Anchor. - ---- - -## ЧАСТЬ C. Мини-датасет (для примеров в статье) - -> Опционально приложить к репозиторию/приложению статьи. - -**customers.csv** - -``` -customer_id,email,phone,city -101,a@ex.com,700,Москва -101,b@ex.com,700,Москва -102,c@ex.com,701,СПб -``` - -**orders.csv** - -``` -order_id,order_date,customer_id -5001,2024-01-10,101 -5002,2024-02-05,102 -``` - -**order_items.csv** - -``` -order_item_id,order_id,product_id,qty,price_at_sale -1,5001,9001,2,100.00 -2,5001,9002,1,50.00 -3,5002,9001,1,100.00 -``` - -**products.csv** - -``` -product_id,name -9001,Phone -9002,Case -``` - -**prices.csv** - -``` -product_id,valid_from,valid_to,price -9001,2023-12-01,2024-01-31,100 -9001,2024-02-01,2999-12-31,110 -``` - ---- - -## ЧАСТЬ D. DDL-скелеты (минимально) - -```sql --- DDS: измерение клиента (Type 2) -CREATE TABLE dds.dim_customer ( - customer_sk BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, - customer_bk VARCHAR NOT NULL, - email VARCHAR, - phone VARCHAR, - city VARCHAR, - valid_from DATE NOT NULL, - valid_to DATE, - is_current BOOLEAN NOT NULL DEFAULT TRUE -); - --- DDS: факт продаж (гранулярность: строка заказа) -CREATE TABLE dds.fact_sales ( - sale_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, - customer_sk BIGINT NOT NULL, - product_sk BIGINT NOT NULL, - date_sk INT NOT NULL, - quantity INT NOT NULL, - amount DECIMAL(18,2) NOT NULL -); -``` - ---- - -## ЧАСТЬ E. Текстовые альтернативы для «капризных» диаграмм - -Если `mindmap`/`quadrantChart` не поддерживаются местом публикации, используйте пункты: - -* **Сводка:** - - * Архитектура: слои STG→ODS→DDS→DM, разделение ответственности, управляемость изменений. - * Модели: 3NF (целостность), Data Vault (масштабируемость), Звезда (производительность), Anchor (гибкая эволюция). - * Понятия: факты, измерения, SCD2, SK/BK. - * Практика: понимать бизнес-задачу, выбирать подход под контекст, строить итеративно. - -* **Интуитивное сравнение моделей (простыми словами):** - Звезда — «быстро стартануть BI»; 3NF — «собрать единый словарь сущностей»; DV/Anchor — «надёжно интегрировать десятки источников и хранить всю историю», но читать сложнее. - ---- - -## Итог - -Статья даёт общий словарь и картинку мира: что за слои в DWH, какие модели бывают и зачем они нужны. Задача менти — почувствовать интуицию различий, научиться видеть место фактов/измерений/SCD и уверенно собрать простую витрину из DDS. Дальше — углубляться по нужной модели в отдельном материале (звезда/DV/Anchor/3NF). diff --git a/dwh-modeling/sql/01_ddl.sql b/dwh-modeling/sql/01_ddl_stg-dds.sql similarity index 100% rename from dwh-modeling/sql/01_ddl.sql rename to dwh-modeling/sql/01_ddl_stg-dds.sql diff --git a/dwh-modeling/sql/02_dim.sql b/dwh-modeling/sql/02_dml_stg-dds.sql similarity index 100% rename from dwh-modeling/sql/02_dim.sql rename to dwh-modeling/sql/02_dml_stg-dds.sql