Чистка заголовков
This commit is contained in:
+31
-30
@@ -1,9 +1,9 @@
|
|||||||
# **Хранилище данных: как устроена аналитика «под капотом»**
|
# Хранилище данных: как устроена аналитика «под капотом»
|
||||||
*Для тех, кто знает SQL, но хочет понять, как хранить данные не в Excel, а по-взрослому*
|
*Для тех, кто знает SQL, но хочет понять, как хранить данные не в Excel, а по-взрослому*
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **Что вы уже умеете — и что узнаете здесь**
|
## Что вы уже умеете — и что узнаете здесь
|
||||||
|
|
||||||
✅ Уже знаете:
|
✅ Уже знаете:
|
||||||
- `SELECT`, `JOIN`, `GROUP BY`;
|
- `SELECT`, `JOIN`, `GROUP BY`;
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **1. Введение: почему нельзя просто SELECT из базы заказов?**
|
## 1. Введение: почему нельзя просто SELECT из базы заказов?
|
||||||
|
|
||||||
Представьте: вы — аналитик в интернет-магазине. Вам нужно ответить на вопрос:
|
Представьте: вы — аналитик в интернет-магазине. Вам нужно ответить на вопрос:
|
||||||
> **«Сколько заказов сделал клиент с email `a@ex.com` за 2023 год, и сколько он потратил?»**
|
> **«Сколько заказов сделал клиент с email `a@ex.com` за 2023 год, и сколько он потратил?»**
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **2. Учебный пример: интернет-магазин**
|
## 2. Учебный пример: интернет-магазин
|
||||||
|
|
||||||
Чтобы всё было на пальцах — разберём простой, но живой пример.
|
Чтобы всё было на пальцах — разберём простой, но живой пример.
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **3. Зачем делить DWH на слои?**
|
## 3. Зачем делить DWH на слои?
|
||||||
|
|
||||||
Представьте, что вы строите дом. Вы же не будете сразу вбивать гвозди в стены — сначала:
|
Представьте, что вы строите дом. Вы же не будете сразу вбивать гвозди в стены — сначала:
|
||||||
1. Привезли стройматериалы (песок, доски, кирпич) — **сырьё**;
|
1. Привезли стройматериалы (песок, доски, кирпич) — **сырьё**;
|
||||||
@@ -121,7 +121,7 @@ flowchart TD
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **4. Путешествие данных: от STG до DM**
|
## 4. Путешествие данных: от STG до DM
|
||||||
|
|
||||||
Давайте проследим, как превращается строка заказа.
|
Давайте проследим, как превращается строка заказа.
|
||||||
|
|
||||||
@@ -189,7 +189,7 @@ flowchart TD
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **5. Базовые понятия: факты, измерения, SCD**
|
## 5. Базовые понятия: факты, измерения, SCD
|
||||||
|
|
||||||
Представьте отчёт:
|
Представьте отчёт:
|
||||||
> *«10 января 2024 года клиент из Москвы (сегмент Premium) купил Phone за 100 ₽»*.
|
> *«10 января 2024 года клиент из Москвы (сегмент Premium) купил Phone за 100 ₽»*.
|
||||||
@@ -245,7 +245,7 @@ erDiagram
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### **SCD Type 2 — как хранить историю**
|
### SCD Type 2 — как хранить историю
|
||||||
|
|
||||||
Клиент №101:
|
Клиент №101:
|
||||||
- с 1 янв по 15 мая — `email = a@ex.com`, `city = Москва`;
|
- с 1 янв по 15 мая — `email = a@ex.com`, `city = Москва`;
|
||||||
@@ -272,11 +272,11 @@ fact_sales.order_date BETWEEN dim_customer.valid_from AND dim_customer.valid_to
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **6. Модели данных для слоя DDS: 4 подхода — и когда какой выбрать**
|
## 6. Модели данных для слоя DDS: 4 подхода — и когда какой выбрать
|
||||||
|
|
||||||
В DDS мы можем хранить данные по-разному. Это не «правильно/неправильно», а **выбор под задачу**.
|
В DDS мы можем хранить данные по-разному. Это не «правильно/неправильно», а **выбор под задачу**.
|
||||||
|
|
||||||
### **1. 3NF (третья нормальная форма)**
|
### 1. 3NF (третья нормальная форма)
|
||||||
*Источник: Билл Инмон (Bill Inmon)*
|
*Источник: Билл Инмон (Bill Inmon)*
|
||||||
|
|
||||||
✅ **Плюсы**:
|
✅ **Плюсы**:
|
||||||
@@ -295,7 +295,7 @@ fact_sales.order_date BETWEEN dim_customer.valid_from AND dim_customer.valid_to
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### **2. Звезда (Star Schema)**
|
### 2. Звезда (Star Schema)
|
||||||
*Источник: Ральф Кимболл (Ralph Kimball)*
|
*Источник: Ральф Кимболл (Ralph Kimball)*
|
||||||
|
|
||||||
✅ **Плюсы**:
|
✅ **Плюсы**:
|
||||||
@@ -314,7 +314,7 @@ fact_sales.order_date BETWEEN dim_customer.valid_from AND dim_customer.valid_to
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### **3. Data Vault 2.0 — «конструктор Lego» для больших DWH**
|
### 3. Data Vault 2.0 — «конструктор Lego» для больших DWH
|
||||||
|
|
||||||
*Идея: Дэн Линстедт (Dan Linstedt). Цель — так организовать хранилище, чтобы можно было спокойно добавлять новые источники и хранить историю, не ломая старую модель.*
|
*Идея: Дэн Линстедт (Dan Linstedt). Цель — так организовать хранилище, чтобы можно было спокойно добавлять новые источники и хранить историю, не ломая старую модель.*
|
||||||
|
|
||||||
@@ -416,7 +416,8 @@ fact_sales.order_date BETWEEN dim_customer.valid_from AND dim_customer.valid_to
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### **4. Anchor Modeling (анкерное моделирование)**
|
### 4. Anchor Modeling (анкерное моделирование)
|
||||||
|
|
||||||
*Источник: Ларс Рёне (Lars Rönnbäck)*
|
*Источник: Ларс Рёне (Lars Rönnbäck)*
|
||||||
|
|
||||||
Ещё более атомарный подход:
|
Ещё более атомарный подход:
|
||||||
@@ -439,7 +440,7 @@ fact_sales.order_date BETWEEN dim_customer.valid_from AND dim_customer.valid_to
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### **Сравнение моделей — наглядно**
|
### Сравнение моделей — наглядно
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
quadrantChart
|
quadrantChart
|
||||||
@@ -459,11 +460,11 @@ quadrantChart
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **7. Практикум: как собрать первую витрину**
|
## 7. Практикум: как собрать первую витрину
|
||||||
|
|
||||||
Покажем на примере `mart_daily_sales` — таблицу, которую можно сразу подключить к BI.
|
Покажем на примере `mart_daily_sales` — таблицу, которую можно сразу подключить к BI.
|
||||||
|
|
||||||
### **Этапы сборки**
|
### Этапы сборки
|
||||||
|
|
||||||
1. Из STG → ODS:
|
1. Из STG → ODS:
|
||||||
- `stg.orders_raw` → `ods.orders` (привели `order_date` к `DATE`);
|
- `stg.orders_raw` → `ods.orders` (привели `order_date` к `DATE`);
|
||||||
@@ -509,9 +510,9 @@ flowchart TD
|
|||||||
DM_SALES --> BI
|
DM_SALES --> BI
|
||||||
```
|
```
|
||||||
|
|
||||||
### **Готовые SQL-скрипты**
|
### Готовые SQL-скрипты
|
||||||
|
|
||||||
Все необходимые скрипты для построения хранилища находятся в папке [`sql/`](dwh-modeling/sql/):
|
Все необходимые скрипты для построения хранилища находятся в папке [`sql/`](sql/):
|
||||||
|
|
||||||
- [`01_ddl_stg-dds.sql`](sql/01_ddl_stg-dds.sql) — создание схем и таблиц (STG, ODS, DDS)
|
- [`01_ddl_stg-dds.sql`](sql/01_ddl_stg-dds.sql) — создание схем и таблиц (STG, ODS, DDS)
|
||||||
- [`02_dml_stg-dds.sql`](sql/02_dml_stg-dds.sql) — загрузка данных и трансформация
|
- [`02_dml_stg-dds.sql`](sql/02_dml_stg-dds.sql) — загрузка данных и трансформация
|
||||||
@@ -520,7 +521,7 @@ flowchart TD
|
|||||||
- [`05_ddl_dm.sql`](sql/05_ddl_dm.sql) — создание витрин (Data Marts)
|
- [`05_ddl_dm.sql`](sql/05_ddl_dm.sql) — создание витрин (Data Marts)
|
||||||
- [`06_dml_dm.sql`](sql/06_dml_dm.sql) — наполнение витрин данными
|
- [`06_dml_dm.sql`](sql/06_dml_dm.sql) — наполнение витрин данными
|
||||||
|
|
||||||
### **Пример SQL-запроса для витрины**
|
### Пример SQL-запроса для витрины
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
-- mart_daily_sales: ежедневные продажи с сегментацией
|
-- mart_daily_sales: ежедневные продажи с сегментацией
|
||||||
@@ -547,7 +548,7 @@ GROUP BY d.date_actual, p.product_name, c.customer_segment;
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **8. Как выбрать модель данных? Советы от практиков**
|
## 8. Как выбрать модель данных? Советы от практиков
|
||||||
|
|
||||||
Выбор модели — **не техническая задача, а стратегическая**.
|
Выбор модели — **не техническая задача, а стратегическая**.
|
||||||
Это как решать: строить дом из кирпича, дерева или SIP-панелей. У каждой технологии — свои плюсы, но **главное — подходит ли она *вам* сегодня**.
|
Это как решать: строить дом из кирпича, дерева или SIP-панелей. У каждой технологии — свои плюсы, но **главное — подходит ли она *вам* сегодня**.
|
||||||
@@ -636,7 +637,7 @@ GROUP BY d.date_actual, p.product_name, c.customer_segment;
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **9. Эксплуатация: качество данных — это не «опция»**
|
## 9. Эксплуатация: качество данных — это не «опция»
|
||||||
|
|
||||||
Самая красивая архитектура бессмысленна, если в `mart_daily_sales` — нули.
|
Самая красивая архитектура бессмысленна, если в `mart_daily_sales` — нули.
|
||||||
Поэтому в каждом слое — **контроль качества (DQ, Data Quality)**.
|
Поэтому в каждом слое — **контроль качества (DQ, Data Quality)**.
|
||||||
@@ -679,7 +680,7 @@ SELECT 'OK' WHERE EXISTS (
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **10. Заключение: главное — понимать «почему»**
|
## 10. Заключение: главное — понимать «почему»
|
||||||
|
|
||||||
Хранилище данных — это не про «крутые технологии», а про **мышление**:
|
Хранилище данных — это не про «крутые технологии», а про **мышление**:
|
||||||
|
|
||||||
@@ -705,7 +706,7 @@ SELECT 'OK' WHERE EXISTS (
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **Приложения**
|
## Приложения
|
||||||
|
|
||||||
### 📚 Мини-глоссарий (RU / EN)
|
### 📚 Мини-глоссарий (RU / EN)
|
||||||
|
|
||||||
@@ -747,11 +748,11 @@ SELECT 'OK' WHERE EXISTS (
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **ЧАСТЬ C. Мини-датасет (для практики)**
|
## ЧАСТЬ C. Мини-датасет (для практики)
|
||||||
|
|
||||||
Все данные для практики находятся в папке [`data/`](data/) — тренируйтесь:
|
Все данные для практики находятся в папке [`data/`](data/) — тренируйтесь:
|
||||||
|
|
||||||
[**`customers.csv`**](data/customers.csv):
|
[`customers.csv`](data/customers.csv):
|
||||||
```csv
|
```csv
|
||||||
customer_id,email,phone,city
|
customer_id,email,phone,city
|
||||||
101,a@ex.com,700,Москва
|
101,a@ex.com,700,Москва
|
||||||
@@ -759,14 +760,14 @@ customer_id,email,phone,city
|
|||||||
102,c@ex.com,701,СПб
|
102,c@ex.com,701,СПб
|
||||||
```
|
```
|
||||||
|
|
||||||
[**`orders.csv`**](data/orders.csv):
|
[`orders.csv`](data/orders.csv):
|
||||||
```csv
|
```csv
|
||||||
order_id,order_date,customer_id
|
order_id,order_date,customer_id
|
||||||
5001,2024-01-10,101
|
5001,2024-01-10,101
|
||||||
5002,2024-02-05,102
|
5002,2024-02-05,102
|
||||||
```
|
```
|
||||||
|
|
||||||
[**`order_items.csv`**](data/order_items.csv):
|
[`order_items.csv`](data/order_items.csv):
|
||||||
```csv
|
```csv
|
||||||
order_item_id,order_id,product_id,qty,price_at_sale
|
order_item_id,order_id,product_id,qty,price_at_sale
|
||||||
1,5001,9001,2,100.00
|
1,5001,9001,2,100.00
|
||||||
@@ -774,14 +775,14 @@ order_item_id,order_id,product_id,qty,price_at_sale
|
|||||||
3,5002,9001,1,100.00
|
3,5002,9001,1,100.00
|
||||||
```
|
```
|
||||||
|
|
||||||
[**`products.csv`**](data/products.csv):
|
[`products.csv`](data/products.csv):
|
||||||
```csv
|
```csv
|
||||||
product_id,name
|
product_id,name
|
||||||
9001,Phone
|
9001,Phone
|
||||||
9002,Case
|
9002,Case
|
||||||
```
|
```
|
||||||
|
|
||||||
[**`prices.csv`**](data/prices.csv):
|
[`prices.csv`](data/prices.csv):
|
||||||
```csv
|
```csv
|
||||||
product_id,valid_from,valid_to,price
|
product_id,valid_from,valid_to,price
|
||||||
9001,2023-12-01,2024-01-31,100
|
9001,2023-12-01,2024-01-31,100
|
||||||
@@ -792,7 +793,7 @@ product_id,valid_from,valid_to,price
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## **ЧАСТЬ D. DDL-скелеты (PostgreSQL)**
|
## ЧАСТЬ D. DDL-скелеты (PostgreSQL)
|
||||||
|
|
||||||
Полные DDL-скрипты для всех слоёв хранилища находятся в файле [`01_ddl_stg-dds.sql`](sql/01_ddl_stg-dds.sql).
|
Полные DDL-скрипты для всех слоёв хранилища находятся в файле [`01_ddl_stg-dds.sql`](sql/01_ddl_stg-dds.sql).
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user