Создание целевого хранилища
Продолжаем работу над хранилищем. Теперь нужно создать целевые таблицы, в которые будет попадать информация из базы-источника. Фактически речь идёт о хранилище данных (data warehouse).
В измерении доставки переименуем поле провинции в ProvinceName, чтобы название было понятным.
В демонстрации используем один SQL Server. В том же списке баз, где лежит исходная база, создадим целевую базу, которая будет играть роль хранилища. В реальной практике источники и хранилище чаще находятся на разных серверах, причём хранилище должно быть мощнее, потому что собирает данные из нескольких систем.
В демонстрационной базе AdventureWorks 2017 несколько предметных областей уже сведены в одну базу: персоны, HR, продажи и другие данные. На практике это были бы отдельные базы: HR-информация, финансы, бухгалтерия и т. п. Их пришлось бы соединять запросом к нескольким источникам.
Создаём базу DW Demo — демонстрационное хранилище данных (data warehouse). При создании выбираем максимально простое логирование (logging), чтобы база не занимала много места.
Измерение сотрудника
Создаём первую таблицу измерения — DimEmployee. Это измерение (dimension) сотрудника.
Сначала создаём внутренний идентификатор. Это не исходный идентификатор сотрудника из источника, а суррогатный ключ (surrogate key) хранилища. Он нужен для быстрой и удобной записи данных. Исходный ключ сотрудника сохраняем отдельно: он понадобится для связи с источником и трассировки.
Поля таблицы:
- EmployeeID — внутренний идентификатор, тип int, первичный ключ (primary key);
- BusinessEntityID — идентификатор сотрудника в исходной системе;
- имя сотрудника — nvarchar(50);
- BirthDate — дата рождения, тип date;
- DepartmentID — идентификатор департамента;
- DepartmentName — название департамента, nvarchar(50);
- StartDate и EndDate — даты перемещения по департаментам, тип date.
Данные для этой таблицы берутся из сотрудников, департаментов и истории перемещений по департаментам. Типы полей сверяются с исходными таблицами. Таблица готова.
Измерение продукта
Следующая таблица — DimProduct, измерение продукта.
Поля таблицы:
- ProductID — внутренний суррогатный ключ, int, первичный ключ;
- исходный ProductID — int;
- ProductName — nvarchar(50);
- ProductCategoryID — int;
- CategoryName — nvarchar(50);
- SubcategoryName — nvarchar(50);
- ModelName — nvarchar(50);
- Color — nvarchar(15);
- ListPrice — тип money;
- StartDate и EndDate — даты истории цены, тип datetime.
Типы полей проверяются по таблицам продуктов, категорий, подкатегорий, моделей и истории цен. При создании важно не забыть назначить первичный ключ. Сохраняем таблицу.
Измерение адреса доставки
Создаём третье измерение — DimAddress, то есть измерение адреса доставки.
Поля таблицы:
- AddressID — внутренний суррогатный идентификатор, int;
- CountryRegionCode — nvarchar(3);
- CountryRegionName — nvarchar(50);
- StateProvinceCode — код провинции;
- StateProvinceID — int;
- ProvinceName — название провинции, nvarchar(50);
- City — город, nvarchar(30).
Данные берутся из адресов, провинций и стран. Название страны лежит в отдельной таблице стран, поэтому её нужно дополнительно присоединить. Если этого не сделать, в измерении не будет названия страны. После добавления соединения получаем регион, провинцию, код и город.
Таблица фактов
Теперь нужна центральная таблица — таблица фактов (fact table). Создаём FactSales — факты продаж.
Поля таблицы:
- EmployeeID — int;
- ProductID — int;
- AddressID — int;
- Date — дата, измерение времени;
- Amount — денежная сумма, тип money;
- Quantity — количество, тип int.
Первичный ключ здесь составной: он объединяет четыре поля — идентификаторы сотрудника, продукта, адреса и дату. Меры в таблице фактов — сумма в деньгах и количество в штуках.
Схема «звезда»
Выносим все созданные таблицы на диаграмму и связываем их. В центре находится FactSales, к ней присоединяются измерения: DimEmployee, DimProduct, DimAddress. Получается схема «звезда» (star schema).
Каждая таблица измерений собирается из данных первичного источника. Затем заполняется центральная таблица фактов. После этого можно переходить к написанию ETL-процедуры (Extract, Transform, Load — извлечение, преобразование, загрузка).
Краткие итоги
Практический смысл материала состоит в переходе от разрозненных операционных данных к управляемой аналитической модели. Сначала выбирается целевая база, которая играет роль хранилища, затем проектируются измерения, и только после этого формируется центральная таблица фактов. Такая последовательность не случайна: она снижает риск ошибок при загрузке и делает структуру предсказуемой для бизнес-анализа.
Ключевая идея — разделение описательных сущностей и измеримых событий. Сотрудник, продукт и адрес доставки выступают измерениями, потому что описывают контекст. Продажа становится фактом, потому что содержит меры — сумму и количество. Если смешать эти роли, аналитические запросы усложняются, а данные хуже поддаются повторному использованию.
Отдельного внимания требует выбор ключей. Суррогатный ключ обеспечивает внутреннюю стабильность хранилища, а бизнес-ключ источника сохраняет связь с исходной системой. Это практично: даже если в источнике изменится формат или логика идентификации, хранилище сможет сохранить историчность и прослеживаемость. Составной ключ таблицы фактов фиксирует уникальность комбинации измерений и не позволяет дублировать одну и ту же продажу.
Денормализация, использованная при сборке измерений, уменьшает число соединений при анализе. Вместо многих таблиц источник превращается в несколько понятных аналитических структур. Это ускоряет отчётность и упрощает работу бизнес-аналитика. Однако такая модель требует аккуратной загрузки: сначала обновляются измерения, затем факты, иначе связи могут нарушиться.
Схема «звезда» здесь выступает не просто диаграммой, а рабочим каркасом для ETL. Она задаёт порядок загрузки, состав полей и точки соединения. Практическое применение такого подхода — создание хранилища, которое поддерживает отчётность, анализ продаж и выявление зависимостей. В результате аналитик получает не набор разрозненных таблиц, а согласованную модель, пригодную для запросов и дальнейшего развития.
Нужно создать целевые таблицы хранилища. В демонстрации используем один SQL Server и создаём базу DW Demo с простым логированием. В реальности источники и хранилище обычно находятся на разных серверах. Цель — собрать данные из AdventureWorks 2017 в денормализованные аналитические таблицы.
Создаём три измерения и одну таблицу фактов.
DimEmployee — измерение сотрудника. Поля: внутренний EmployeeID типа int как первичный ключ, BusinessEntityID из источника, имя сотрудника nvarchar(50), BirthDate date, DepartmentID, DepartmentName nvarchar(50), StartDate и EndDate date. Данные берутся из сотрудников, департаментов и истории перемещений.
DimProduct — измерение продукта. Поля: внутренний ProductID int как первичный ключ, исходный ProductID int, ProductName nvarchar(50), ProductCategoryID int, CategoryName nvarchar(50), SubcategoryName nvarchar(50), ModelName nvarchar(50), Color nvarchar(15), ListPrice money, StartDate и EndDate datetime. Даты относятся к истории цены.
DimAddress — измерение адреса доставки. Поля: AddressID int как внутренний ключ, CountryRegionCode nvarchar(3), CountryRegionName nvarchar(50), StateProvinceCode, StateProvinceID int, ProvinceName nvarchar(50), City nvarchar(30). Чтобы получить название страны, нужно соединить адреса, провинции и страны.
FactSales — таблица фактов продаж. Поля: EmployeeID int, ProductID int, AddressID int, Date, Amount money, Quantity int. Первичный ключ составной: EmployeeID, ProductID, AddressID и Date. Меры — Amount и Quantity.
Затем строим схему «звезда»: FactSales в центре, к ней присоединяются DimEmployee, DimProduct и DimAddress. Данные из источника сначала попадают в измерения, затем заполняется таблица фактов. После этого можно писать ETL-процедуру.
1. Хранилище можно создать как отдельную базу на том же сервере в демонстрации, но в продакшене его размещают отдельно.
2. Целевые таблицы строятся по модели «звезда»: измерения и центральная таблица фактов.
3. Для каждой таблицы измерений нужен суррогатный первичный ключ.
4. Бизнес-ключ источника сохраняется для связи и трассировки.
5. Типы целевых полей выбираются по исходным данным.
6. Денормализация сокращает число таблиц, необходимых для анализа.
7. Измерение сотрудника собирается из HR-данных, департаментов и истории перемещений.
8. Измерение продукта включает категорию, подкатегорию, модель, цвет и цену.
9. Измерение адреса требует соединения адреса, провинции и страны.
10. Таблица фактов продаж содержит ключи измерений, дату и меры.
11. Составной первичный ключ факта обеспечивает уникальность комбинации измерений.
12. После схемы «звезда» создаётся ETL-процедура загрузки.
1. Зачем в хранилище создавать отдельную целевую базу?
2. Чем суррогатный ключ отличается от бизнес-ключа?
3. Почему в измерении сотрудника сохраняют исходный идентификатор?
4. Какие поля образуют измерение сотрудника?
5. Как выбираются типы данных для целевых полей?
6. Какие атрибуты включает измерение продукта?
7. Почему для измерения адреса нужно соединять несколько таблиц?
8. Какие меры содержит таблица фактов продаж?
9. Почему ключ таблицы фактов составной?
10. Как в схеме «звезда» связаны факты и измерения?
11. В чём практический смысл денормализации?
12. Что подготавливается перед написанием ETL-процедуры?