Введение в OLAP и хранилища данных

ETL процедура. Загрузка таблицы фактов. Часть 1

Рассматривается завершающий этап ETL (Extract, Transform, Load — извлечение, преобразование, загрузка): загрузка фактов продаж в хранилище после заполнения измерений. Показано, как настроить суррогатные ключи, извлечь отправленные заказы, сопоставить их с адресами и продуктами через Lookup, учесть актуальность цены на дату заказа и обработать ошибки сопоставления.

Основные мысли

В результате изучения лекции слушатель будет способен:
1. Объяснять назначение суррогатных ключей и автоинкремента в измерениях.
2. Определять состав полей, необходимых для загрузки фактов продаж.
3. Различать роли SalesOrderHeader и SalesOrderDetail.
4. Применять фильтр Status = 5 для отбора отправленных заказов.
5. Настраивать Lookup для сопоставления фактов с измерениями адреса и продукта.
6. Анализировать необходимость учета актуальности цены на дату заказа.
7. Оценивать последствия ошибок сопоставления и выбирать способ их обработки.
8. Проектировать загрузку фактов с контролем ошибок и частичным кешированием.
Показывать лекцию целиком
Краткое изложение

Загрузка фактов в хранилище данных

1. Настройка суррогатных ключей измерений

В хранилище каждое измерение (dimension) — продукт, сотрудник, адрес — имеет два вида ключей. Первый — бизнес-ключ (естественный идентификатор из источника). Второй — суррогатный ключ (surrogate key). Это внутренний идентификатор хранилища, не связанный с исходным идентификатором из базы данных.

Чтобы не создавать суррогатный ключ вручную, используется автоинкремент (autoincrement). Сервер сам генерирует значения: 1, 2, 3 и так далее. Автоинкремент включается для ключей измерений Address, Employee и Product. После настройки схема сохраняется.

2. Извлечение фактов продаж

Источник фактов — база FactDB. Для выгрузки используется SQL-запрос. Он должен вернуть:

Одного города для идентификации адреса недостаточно. В разных регионах могут встречаться города с одинаковыми названиями. Уникальной является пара «город + регион». Поэтому в запросе используются City и StateProvinceID.

SalesOrderHeader — это таблица заголовков заказов, то есть чеков. В ней хранятся номер заказа, Revision, OrderDate, DueDate, ShipDate, Status, SalesPersonID и Total. SalesOrderDetail — таблица детализации заказа. В ней есть SalesOrderID, номер позиции, ProductID, Quantity и LineTotal. Позиция внутри заказа уникально определяется парой «SalesOrderID + номер позиции».

В запросе таблица Person соединяется с SalesOrderHeader по адресу доставки, а затем с SalesOrderDetail — по номеру заказа. Важное условие задания: нужно загружать только заказы в состоянии «отправлено». Это соответствует Status = 5. Поле Status находится в SalesOrderHeader.

3. Сопоставление фактов с измерениями

Измерения и факты загружаются в хранилище отдельно. Поэтому нужно явно указать, как каждая продажа связана со своими измерениями. Для этого используется Lookup (поиск/уточняющий запрос). Чтобы не загружать оперативную память, применяется частичное кеширование (caching).

3.1. Сопоставление адресов

Lookup ищет соответствие в таблице Address хранилища. Условия сопоставления:

Такая пара обеспечивает уникальность «город + регион». Поле DV Address — суррогатный ключ, который генерируется автоинкрементом. Если адрес не найден, компонент останавливается. Если адрес найден, его идентификатор передается дальше и позднее попадает в таблицу фактов.

3.2. Сопоставление продуктов

Сначала отбираются записи, для которых адрес уже сопоставлен. Затем выполняется Lookup по продукту. Основное условие: ProductID = ProductID. Поле DV ProductID — первичный ключ, который генерируется автоматически.

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

Цена продукта должна быть актуальной на момент покупки. В простом Lookup можно связать OrderDate только с StartDate, но это неверно. Нужно перейти в Advanced и изменить запрос:

Так выбирается версия продукта с ценой, которая действовала на дату заказа.

4. Результат загрузки

После сопоставления в центральную таблицу фактов попадают суррогатные ключи измерений и меры: Quantity, LineTotal, OrderDate и другие атрибуты. Несопоставленные продукты не удаляются, а попадают в файл ошибок. Это делает загрузку контролируемой и устойчивой.

Краткие итоги

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

Основная сложность связана с неоднозначностью источников. Адрес нельзя надежно определить только по названию города, поскольку одинаковые названия встречаются в разных регионах. Поэтому правило сопоставления должно опираться на составной бизнес-ключ. Продукт также требует не только идентификатора, но и учета временной актуальности цены. Если цена зависит от периода, то выбор версии продукта должен происходить по дате заказа, а не по формальному совпадению одного поля. Это показывает, что загрузка фактов — не механическая операция, а этап применения бизнес-правил.

Отдельного внимания требует обработка ошибок. Не все продажи можно сопоставить с измерениями. Причины могут быть объективными: товар продан, но отсутствует в реестре, или адрес не найден в заранее загруженном измерении. Если такие случаи игнорировать, хранилище потеряет часть данных и даст искаженную картину. Поэтому ошибки нужно изолировать, сохранять и анализировать. Остановка компонента при критическом несоответствии адреса и выгрузка ошибок по продуктам — это разные стратегии контроля, зависящие от природы ошибки.

Частичное кеширование и поэтапное сопоставление снижают нагрузку на память и делают процесс управляемым. Сначала проверяется адрес, затем продукт. Такая последовательность упрощает отладку и позволяет точно определить, на каком шаге возникло несоответствие. В результате формируется не просто набор фактов, а связанная модель, где каждая продажа получает корректные ссылки на измерения и меры.

С практической точки зрения такой подход важен для надежности отчетности. Если сопоставление выполнено неверно, аналитика будет содержать дубли, пропуски или неверные цены. Поэтому контроль качества на этапе загрузки фактов не менее важен, чем скорость загрузки. Он обеспечивает доверие к данным и позволяет использовать хранилище для принятия решений.

1. Ключи измерений

Каждое измерение — продукт, сотрудник, адрес — имеет бизнес-ключ и суррогатный ключ. Суррогатный ключ — внутренний идентификатор хранилища. Для его генерации используется автоинкремент. Его включают для ключей Address, Employee и Product.

2. Извлечение фактов

Источник фактов — FactDB. SQL-запрос выгружает данные продаж. Для адреса берутся City и StateProvinceID, потому что одинаковые названия городов могут быть в разных регионах. Также выгружаются SalesPersonID, ProductID, Quantity, LineTotal и OrderDate.

SalesOrderHeader — это чек. В нем есть номер заказа, даты, статус, продавец и сумма. SalesOrderDetail — позиции чека. Позиция определяется парой «SalesOrderID + номер позиции». В запросе Person соединяется с SalesOrderHeader по адресу доставки, затем с SalesOrderDetail по номеру заказа.

Нужно загружать только отправленные заказы. Это Status = 5. Поле Status находится в SalesOrderHeader.

3. Сопоставление с измерениями

Измерения и факты загружаются отдельно. Для связи используется Lookup. Применяется частичное кеширование.

Сначала сопоставляется адрес. Условия: City = City и StateProvinceID = StateProvinceID. Если адрес не найден, компонент останавливается. Если найден, берется DV Address.

Затем сопоставляется продукт. Условие: ProductID = ProductID. Ошибки по продуктам выгружаются в отдельный файл. Продукт может отсутствовать, если товар продан, но не занесен в реестр.

Цена должна быть актуальной на дату заказа. В Advanced Lookup нужно задать условие: OrderDate BETWEEN StartDate AND EndDate. Тогда выбирается правильная версия цены.

4. Итог

В таблицу фактов попадают суррогатные ключи измерений и меры: Quantity, LineTotal, OrderDate и другие. Несопоставленные продукты сохраняются в файле ошибок. Это делает загрузку контролируемой и устойчивой.

Выводы

1. Суррогатные ключи измерений удобно генерировать автоинкрементом.
2. Для идентификации адреса нужна пара «город + регион».
3. Факты продаж извлекаются из FactDB через SQL-запрос.
4. SalesOrderHeader хранит данные чека, SalesOrderDetail — позиции.
5. Загружаются только отправленные заказы со Status = 5.
6. Измерения и факты загружаются отдельно, поэтому нужно сопоставление.
7. Lookup связывает бизнес-ключи источника с суррогатными ключами хранилища.
8. Частичное кеширование снижает нагрузку на оперативную память.
9. При ошибке сопоставления адреса компонент останавливается.
10. Ошибки по продуктам выгружаются в отдельный файл.
11. Цена продукта выбирается по интервалу StartDate–EndDate.
12. В таблицу фактов попадают суррогатные ключи и меры.

Вопросы для самопроверки

1. Почему в измерениях создаются суррогатные ключи?
2. Как настроить автоинкремент для ключей измерений?
3. Почему для адреса недостаточно только названия города?
4. Какие таблицы участвуют в извлечении фактов продаж?
5. Чем SalesOrderHeader отличается от SalesOrderDetail?
6. Как уникально идентифицировать позицию внутри заказа?
7. Какие поля выгружаются из фактов продаж?
8. Почему нужно фильтровать заказы по Status = 5?
9. Зачем нужен Lookup при загрузке фактов?
10. Как сопоставляются адреса и продукты?
11. Как учитывается актуальность цены на дату заказа?
12. Как обрабатываются ошибки сопоставления?
Вернуться к учебному плану