diff --git a/.gitignore b/.gitignore index 4c49bd7..e58e5a2 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .env +.idea diff --git a/dwh-modeling/README.md b/dwh-modeling/README.md index 634323c..e80daba 100644 --- a/dwh-modeling/README.md +++ b/dwh-modeling/README.md @@ -1,10 +1,3 @@ -Отлично! Вот **связный, литературный и педагогически выстроенный** вариант статьи, адаптированный под новичков (студентов с базовым SQL), но без упрощения сути. Я убрал «рыхлые» места, усилил плавность повествования, добавил пояснения «на пальцах» — и сохранил все важные детали: архитектурные слои, модели данных, SCD, ключи, антипаттерны. - -Статья оформлена как **обучающий материал** — с логикой «от боли к решению», с живым примером (интернет-магазин), с акцентом на *почему*, а не только *как*. -Готова к публикации на Habr, с приложенным GitHub-репозиторием. - ---- - # **Хранилище данных: как устроена аналитика «под капотом»** *Для тех, кто знает SQL, но хочет понять, как хранить данные не в Excel, а по-взрослому* @@ -132,12 +125,12 @@ flowchart TD Давайте проследим, как превращается строка заказа. -### **STG (Staging / «Бронза»)** — «как пришло» +### **STG (Staging / Bronze)** — «как пришло» - Таблицы: `stg.orders_raw`, `stg.customers_raw`; - Структура — *точно как в источнике* (может быть `VARCHAR` даже у дат); - Добавлены технические поля: - - `_ingest_id` — идентификатор загрузки; + - `_load_id` — идентификатор загрузки; - `_load_ts` — время получения данных; - Главное правило: **неизменяемость**. Если пришла новая порция — либо добавляем новые строки, либо *полностью перезагружаем* слой (идемпотентность). - Дедупликация: если два раза пришёл один и тот же заказ — оставляем один (по `order_id + _load_ts`). @@ -146,7 +139,7 @@ flowchart TD --- -### **ODS (Operational Data Store / «Серебро»)** — «почистили, но не трогали смысл» +### **ODS (Operational Data Store / Silver)** — «почистили, но не трогали смысл» - Таблицы: `ods.orders`, `ods.customers`; - Здесь: @@ -161,7 +154,7 @@ flowchart TD --- -### **DDS (Data Delivery Store / «Ядро», «Золото»)** — «интеграция + история» +### **DDS (Data Delivery Store / Core / Gold)** — «интеграция + история» Здесь рождается *единая бизнес-модель*. Появляются понятия: **измерения**, **факты**, **суррогатные ключи**, **SCD**. @@ -192,7 +185,7 @@ flowchart TD - `dm.mart_daily_sales` — ежедневные продажи по товарам и сегментам; - `dm.mart_customer_360` — полный портрет клиента: сколько потратил, когда заходил, какие товары любит. -Они построены по модели **Звезда (Star Schema)** — потому что BI-инструментам так удобнее всего. +Они часто построены по модели **Звезда (Star Schema)** — потому что BI-инструментам так удобнее всего. --- @@ -257,7 +250,7 @@ fact_sales.order_date BETWEEN dim_customer.valid_from AND dim_customer.valid_to ``` и получаем актуальный на тот день email и город. -> 🔍 Подробнее про SCD — в отдельной статье [SQC](SCD.md) (сравнение Type 1/2/3, паттерны обновления). +> 🔍 Подробнее про SCD — в отдельной статье [Slow Changing Dimensions](SCD.md) (сравнение Type 1/2/3, паттерны обновления). --- @@ -269,16 +262,18 @@ fact_sales.order_date BETWEEN dim_customer.valid_from AND dim_customer.valid_to *Источник: Билл Инмон (Bill Inmon)* ✅ **Плюсы**: -- Максимальная **целостность** — дубликатов нет (все атрибуты — там, где должны быть); -- Легко **расширять** — добавили новый источник? Расширили связанный справочник. +- Минимум избыточности при строгих ключах и правилах дедупликации. +- Проще поддерживать единую терминологию и НСИ (reference data). +- Атрибуты и справочники легко расширять. ❌ **Минусы**: -- Запросы сложные: много JOIN’ов даже для простого отчёта; -- Тяжело новичкам: «а где город клиента?» → нужно пройти `customer → address → city`. +- Много JOIN даже для простых отчётов. +- Историчность (SCD2) усложняет таблицы. +- Новые источники дороже гармонизировать (привести к канону). 📌 **Когда выбирать**: → Корпоративные DWH, где важна *единая терминология* и *долгосрочная поддержка*. -→ Когда источников — десятки, и нужно гарантировать консистентность. +→ Стабильные домены (финансы, НСИ, договоры) и умеренная динамика изменений. --- diff --git a/dwh-modeling/sql/02_dim.sql b/dwh-modeling/sql/02_dim.sql index e606904..3eeecb4 100644 --- a/dwh-modeling/sql/02_dim.sql +++ b/dwh-modeling/sql/02_dim.sql @@ -56,7 +56,8 @@ WITH src AS ( s._load_id, s._load_ts, COALESCE(NULLIF(s.event_ts, '')::timestamp, s._load_ts, - to_timestamp(regexp_replace(s._load_id,'^batch_',''),'YYYYMMDD_HH24MI')) AS eff_ts + to_timestamp(regexp_replace(s._load_id,'^batch_',''),'YYYYMMDD_HH24MI')) + AS eff_ts FROM stg.customers_raw s WHERE s.customer_id ~ '^\d+$' ),