SQLLab
Теория· 15 мин· 20 XP

Шаги проектирования хранилища данных

Проектирование DWH по Kimball (Dimensional Modeling):

1. Определить бизнес-процесс

Что анализируем? Примеры:

  • Продажи в магазинах
  • Клики на сайте
  • Звонки в колл-центре

2. Выбрать grain (зерно факта)

Grain — самый детальный уровень данных в fact-таблице.

Например:

  • Одна строка = одна позиция заказа (order_id + product_id)
  • Одна строка = один заказ (order_id)
  • Одна строка = один день в одном магазине

Выбор grain определяет всё остальное.

3. Определить измерения

Что является контекстом для факта?

  • Кто? → dim_customer
  • Что? → dim_product
  • Где? → dim_store
  • Когда? → dim_date

4. Определить метрики факта

Числовые аддитивные показатели:

  • revenue, cost, profit, quantity

Аддитивные: можно суммировать по любому измерению Полуаддитивные: можно суммировать не по всем (например, остаток на складе) Неаддитивные: нельзя суммировать (курс валюты, коэффициенты)

5. Определить медленно меняющиеся измерения

Что меняется со временем?

  • Тир лояльности покупателя → SCD Type 2
  • Адрес магазина → SCD Type 1 (если история не нужна)
  • Цена товара → зависит от требований

6. ETL-процесс

Как и когда данные будут загружаться в DWH?

  • Batch (ночная загрузка)
  • Near real-time (каждые N минут)
  • Streaming (каждую секунду)

Наш проект использует исторический batch: данные за Jan–Jun 2024.

Conformed dimensions — одно измерение на много фактов

Если бы в DWH появилась вторая факт-таблица (например, fact_returns для возвратов), у нас есть выбор: сделать для неё отдельное dim_date или переиспользовать существующее. Измерение, которое используется несколькими факт-таблицами без изменений — это conformed dimension (согласованное измерение).

Выгода: покупатель с customer_id = 9 в dim_customer — это один и тот же покупатель что для fact_sales, что для fact_returns. Это позволяет строить отчёты, которые объединяют несколько факт-таблиц через общее измерение («выручка и возвраты по одному и тому же покупателю»), не изобретая сопоставление ключей заново.

Три типа факт-таблиц

  • Transaction fact — одна строка на одно событие. fact_sales — ровно этот тип: строка появляется в момент продажи и больше не меняется.
  • Periodic snapshot — одна строка на сущность за период (например, остаток товара на складе на конец каждого дня), даже если за этот период ничего не происходило.
  • Accumulating snapshot — одна строка на процесс целиком, которая обновляется по мере прохождения этапов (например, заказ: дата оформления → дата отгрузки → дата доставки в одной и той же строке).

Большинство учебных примеров DWH — transaction fact, но в реальных проектах часто нужны все три вида одновременно для разных вопросов бизнеса.

Частые ошибки

  • Выбирают grain после того, как уже начали писать ETL — если зерно выбрано неверно, приходится переделывать и схему, и загрузку. Grain — первое решение, не последнее.
  • Делают отдельное измерение под каждую факт-таблицу — там, где сущность одна и та же (например, покупатель), это должно быть одно conformed dimension, а не дублирующиеся копии.
  • Путают periodic snapshot с transaction fact — если бизнесу нужен ответ на вопрос «сколько было на складе на конец каждого дня», а не «когда произошла операция», transaction fact для этого не годится в принципе — нужен snapshot с одной строкой на день, даже без движений.

Запомни

Методология Kimball — bottom-up от конкретного бизнес-процесса, не попытка сразу построить универсальную схему на всё. Grain — первое и самое важное решение. Conformed dimension — одно измерение, общее для нескольких факт-таблиц. Три типа фактов — transaction (событие), periodic snapshot (срез на момент), accumulating snapshot (прогресс процесса, строка обновляется).

Микро-практика

  • Нужен отчёт «остаток на складе на конец каждого дня, даже если движений не было» → periodic snapshot fact.
  • Заказ проходит статусы оформлен → оплачен → отгружен → доставлен, и нужно видеть время между этапами в одной строке → accumulating snapshot fact.
  • Строится вторая факт-таблица для возвратов, а покупатели — те же, что и в продажах → переиспользовать существующее dim_customer как conformed dimension, не создавать новое.

Прочитайте урок до конца — прогресс засчитается автоматически