Skip to content

DWH, SCD и таблицы фактов ​

OLTP и OLAP ​

OLTP (Online Transaction Processing) и OLAP (Online Analytical Processing) — два разных подхода к работе с данными.

OLTP-системы обрабатывают операционные транзакции: создание заказа, добавление товара, проведение оплаты и изменение статуса. Такие операции обычно быстрые, затрагивают небольшое количество строк и должны выполняться согласованно.

Для OLTP особенно важны:

  • транзакции;
  • ограничения целостности;
  • блокировки и изоляция;
  • нормализация данных;
  • операции INSERT, UPDATE и DELETE.

Типичная структура OLTP-базы интернет-магазина:

text
customer
   |
   +--- order
          |
          +--- order_item
                   |
                   +--- product

OLAP-системы предназначены для аналитических запросов: расчета выручки по месяцам, сравнения продаж по регионам, поиска наиболее продаваемых товаров и анализа динамики показателей. Один запрос может читать миллионы строк и использовать GROUP BY и несколько JOIN.

ХарактеристикаOLTPOLAP
Основная задачаОбработка операцийАнализ данных
Тип запросовКороткиеСложные
Изменение данныхЧастоеОбычно пакетная загрузка
СтруктураНормализованнаяЧасто денормализованная
Основная нагрузкаINSERT, UPDATE, DELETESELECT, GROUP BY, JOIN
ИсторияНе всегда хранитсяОбычно важна

DWH ​

DWH (Data Warehouse), или хранилище данных, — система для накопления и аналитической обработки данных из различных источников.

Источниками DWH могут быть:

  • OLTP-базы;
  • CRM и ERP;
  • файлы;
  • внешние сервисы;
  • другие информационные системы.

Обобщенный поток данных выглядит так:

text
OLTP / CRM / ERP / Files
          |
          v
        ETL/ELT
          |
          v
         DWH
          |
          v
        BI / OLAP

В отличие от операционной базы, DWH хранит данные прежде всего для анализа. Операционная база может содержать таблицы customer, order, order_item, product, а в DWH те же данные могут быть преобразованы в:

text
dim_customer
dim_product
dim_date
dim_store
fact_sales

Такая структура отделяет операционную работу приложения от аналитической нагрузки.

Загрузка данных в DWH ​

Данные из OLTP-системы не обязательно копируются в DWH один к одному. Во время загрузки могут выполняться:

  • очистка данных;
  • преобразование типов;
  • объединение источников;
  • устранение дубликатов;
  • расчет дополнительных показателей;
  • сохранение истории изменений.

Таким образом, DWH — не просто копия операционной базы, а подготовленная для анализа модель данных.


SCD ​

SCD (Slowly Changing Dimension), или медленно изменяющееся измерение, — механизм отслеживания изменений атрибутов измерения во времени. Он применяется, когда данные меняются не очень часто и важно сохранить их историческое состояние.

Например, клиент может изменить город. В операционной системе достаточно хранить актуальное значение, а в DWH может потребоваться ответить, в каком городе находился клиент в момент совершения покупки.

Постановка проблемы ​

Есть данные о платежах:

payment_idcustomer_idstaff_idstore_idamount
1711500
21012700

И данные по сотрудникам:

staff_idfiostore_id
1Иванов Петр1
2Максим Сергеевич2

По текущему значению store_id нельзя надежно определить, в каком магазине работал сотрудник во время каждой продажи. SCD решает эту задачу разными способами.

Тип 0 (SCD0) ​

Пассивный метод: предполагается, что значения атрибутов не будут меняться.

customer_idfioborn_dateborn_citypassport
1Иванов Петр01.05.1974Самара4477 050607

Дату и место рождения можно считать неизменяемыми атрибутами, тогда как ФИО и паспорт потенциально могут измениться.

Тип 1 (SCD1) ​

Используется простое перезаписывание данных. История изменений полностью теряется.

customer_idfioborn_dateborn_citypassport
1Семенов Петр01.05.1974Самара5588 323344

После изменения ФИО и паспорта исходные значения уже недоступны.

Тип 2 (SCD2) ​

При изменении добавляется новая строка и служебные столбцы для версионности.

customer_idfioborn_dateborn_citypassportactivecreated_date
1Иванов Петр01.05.1974Самара4477 050607false01.01.2020
1Семенов Петр01.05.1974Самара5588 323344true17.06.2021

История сохраняется, но появляется избыточность. Для управления версиями также часто используют valid_from, valid_to и is_current.

Тип 3 (SCD3) ​

Предыдущее значение хранится в дополнительных столбцах.

Исходное состояние:

customer_idfiopassportold_fioold_passportchange_date
1Иванов Петр4477 050607nullnullnull

После изменения:

customer_idfiopassportold_fioold_passportchange_date
1Семенов Петр5588 323344Иванов Петр4477 05060717.06.2021

Метод сохраняет ограниченную историю: количество изменений определяется числом заранее созданных столбцов.

Тип 4 (SCD4) ​

Текущие данные хранятся в основной таблице, а изменения — в отдельной исторической таблице.

Основная таблица:

customer_idfioborn_dateborn_citypassportactual_date
1Семенов Петр01.05.1974Самара5588 32334417.06.2021

Таблица изменений:

customer_idfiopassportactual_date
1Иванов Петр4477 05060701.01.2020

Основная таблица остается компактной и содержит актуальную информацию, а историю можно получить через отдельную таблицу.

Тип 5 (SCD5) ​

Type 5 сочетает Type 4 и Type 1. История хранится в отдельной таблице, а в основном измерении добавляется ссылка на текущее мини-измерение.

Мини-измерение:

profile_idage_groupincome_group
125-34Средний
235-44Высокий

В таблице фактов может храниться историческая ссылка на мини-измерение, а current_profile_id в основном измерении обновляется по правилам Type 1. Поэтому старые факты сохраняют прежний профиль, но актуальный профиль также доступен.

Тип 6 (SCD6) ​

Type 6 объединяет Type 1, Type 2 и Type 3. История хранится в отдельных строках измерения, а в каждой строке дополнительно сохраняется текущее значение атрибута.

customer_keycustomer_idcitycurrent_cityvalid_fromvalid_tois_current
110МоскваСанкт-Петербург2025-01-012026-03-01false
210Санкт-ПетербургСанкт-Петербург2026-03-01NULLtrue

city показывает значение в соответствующий период, а current_city — актуальное значение. Поэтому можно выполнять анализ как «на момент события», так и по текущему состоянию.

Тип 7 (SCD7) ​

Type 7 поддерживает исторический и текущий взгляд через две ссылки в таблице фактов:

  • ссылку на историческую версию измерения;
  • ссылку на устойчивый идентификатор сущности.
customer_keycustomer_idcityis_current
110Москваfalse
210Санкт-Петербургtrue

В таблице фактов могут находиться:

fact_idhistorical_customer_keycustomer_idamount
10011103000

historical_customer_key позволяет получить состояние клиента на момент покупки, а customer_id — обратиться к текущей версии.

Сравнение типов SCD ​

ТипОсновной механизмОсобенность
Type 0Не изменять атрибутИстория сохраняется без обработки изменений
Type 1ПерезаписьИстория теряется
Type 2Новая строка версииПолная история изменений
Type 3Старое значение в отдельном столбцеОграниченная история
Type 4Отдельная таблица историиТекущее и историческое состояние разделены
Type 5Type 4 + Type 1История и текущее мини-измерение
Type 6Type 1 + Type 2 + Type 3Историческое и текущее значение в строках версий
Type 7Две ссылки из фактаИсторический и текущий взгляд

Выбор типа зависит от требуемой аналитики. Представления, секционирование, вычисляемые столбцы, триггеры и процедуры могут помогать хранить историю и поддерживать целостность данных.


Таблицы фактов ​

Таблица фактов содержит показатели бизнес-процессов и ссылки на измерения, по которым эти показатели анализируются.

Например, продажу товара можно представить так:

date_idproduct_idcustomer_idstore_idquantityamount
110110523000
110210511500
210115734500

date_id, product_id, customer_id и store_id — ссылки на измерения, а quantity и amount — показатели.

Классификация таблиц фактов ​

В подходе Kimball выделяют:

  • транзакционные факты — строка соответствует событию или элементу транзакции: продаже, платежу, заказу;
  • факты периодического снимка — состояние процесса на определенный момент: остаток на конец дня, баланс на конец месяца;
  • факты накопительного снимка — один процесс от начала до завершения, например заказ со стадиями «создан → оплачен → доставлен»;
  • factless fact table — строка фиксирует событие или состояние без числовых показателей: посещение занятия или доступность товара.

Таблицы измерений ​

Измерение содержит описание объекта, по которому анализируются факты.

Измерение товара:

product_idproduct_namecategory
101НоутбукЭлектроника
102МониторЭлектроника

Измерение даты:

date_iddatemonthyear
12026-01-1012026
22026-01-1112026

Пример аналитического запроса:

sql
SELECT
    d.year,
    p.category,
    SUM(f.amount) AS revenue
FROM fact_sales f
JOIN dim_date d ON d.date_id = f.date_id
JOIN dim_product p ON p.product_id = f.product_id
GROUP BY
    d.year,
    p.category;

Зерно таблицы фактов ​

Зерно — это то, что представляет одна строка таблицы фактов. Например:

Одна строка fact_sales — одна позиция товара в одном заказе.

Все измерения и показатели должны соответствовать этому уровню детализации. Если в одной строке одновременно хранить позицию товара и итоговую сумму всего заказа, смешиваются разные уровни детализации и аналитические результаты становятся неоднозначными.

Типы фактов ​

  • Аддитивные можно складывать по всем измерениям: quantity, amount.
  • Полуаддитивные можно складывать только по некоторым измерениям. Остаток товара можно суммировать по товарам, но обычно нельзя складывать остатки по датам.
  • Неаддитивные нельзя корректно суммировать. Например, margin_percent требует специальной агрегации.