Классика баз данных - статьи

       

Проектирование структуры реляционного хранилища данных


Хранилища строятся на основе многомерной модели данных, подразумевающей выделение отдельных измерений (время, география, клиент, счет) и фактов (объем продаж, доход, количество товара) с их анализом по выбранным измерениям. Многомерная модель данных физически может быть реализована как в многомерных, так и в реляционных СУБД. В последнем случае она выполняется по схеме «звезда» или «снежинка». Данные схемы предполагают выделение таблиц фактов и таблиц измерений. Каждая таблица фактов содержит детальные данные и внешние ключи на таблицы измерений.

Теория построения многомерной модели данных и ее воплощение в реляционной структуре известна [3, 10, 12], однако информации по проблеме представления иерархий очень мало. В качестве примера измерения, широко применяющегося при анализе деятельности предприятия и имеющего иерархическую структуру, можно привести справочник статей затрат (рис 2).

Рис. 2. Модель иерархического справочника.

Таблица 1. Представление иерархий с помощью рекурсивной связи

Классически проблема представления иерархий решается с помощью рекурсивной связи, что позволяет помещать в одной таблице дерево любой глубины и размерности. В нашем случае рассматриваемые данные представлены в виде таблицы 1. Однако в простоте этого решения скрывается и основной его недостаток: стандарт SQL не поддерживает рекурсивные указатели, поэтому для представления деревьев в хранилище данных используют другие методы.

Метод, предложенный Джо Селко [4], основан на теории множеств — все узлы дерева проходятся в прямом порядке [5] и для каждого узла заполняются два значения (cм. нумерацию узлов на рис. 3).



Рис. 3. Нумерация левой и правой границ узлов дерева

Сначала заполняется левая граница и лишь затем правая — при движении обратно от потомков к родителям. При такой нумерации узлов каждый родитель содержит потомков, левая и правая граница которых лежит в интервале между левой и правой границей родителя. Аналогично все родители потомка имеют левую границу, которая меньше левой границы потомка и правую, большую правой границы потомка.
Следовательно, сумму затрат для конкретного места возникновения затрат и всех его составляющих можно получить одним запросом. Например, для получения затрат по инфраструктуре можно выполнить следующий SQL-запрос:

select sum(fact_table.cost)

from fact_table, dimension_table D1, dimension_table D2

where fact_table.dimension_id = D2.id

and D2.left >= D1.left

and D2.right <= D1.right

and D1.name = «Инфраструктура»


Для простоты работы с таким справочником кроме полей left, right стоит добавить еще два поля: «Level» — уровень узла в дереве, «Is_leaf» — флаг, показывающий является ли узел листом в дереве или нет. Таким образом, мы получаем таблицу «dimension_table» (таблица 2), которая позволяет хранить дерево любой глубины вложенности и размерности и выбирать потомков и родителей с помощью одного запроса.





Таблица 2. Представление иерархий с помощью левой и правой границ




Таблица 3. Структура и содержание вспомогательной таблицы
Другой способ, описанный Ральфом Кимбаллом [6], основан на введении вспомогательной таблицы («helper-table»), через которую осуществляется связь таблицы фактов с таблицей измерения. Эта вспомогательная таблица отражает иерархическую структуру измерения и подчиняется следующему закону: вспомогательная таблица содержит весь набор пар «родитель-потомок», причем потомок может не быть непосредственным потомком родителя. Структура такой таблицы и ее содержимое показано в таблице 3.

Связывая таблицу фактов (рис. 4) с идентификатором потомка во вспомогательной таблице, а таблицу измерений с идентификатором родителя, мы можем вычислять сумму затрат для каждого места возникновения затрат и всех его составляющих одним запросом, как и в предыдущем случае. При этом, добавляя ограничения на поля «Distance» и «Is Leaf», мы можем легко считать затраты для любого уровня в иерархии.




Рис. 4. Модель иерархического справочника с вспомогательной таблицей
Например, для того, чтобы посчитать сумму затрат, возникающих в местах, находящихся по иерархии на один уровень ниже «Инфраструктуры», необходимо выполнить следующий SQL-запрос:



select sum(fact_table.cost)

from fact_table, dimension_table, helper_table

where fact_table.dimension_id = helper_table.child_id

and dimension_table.dimension_id = helper_table.parent_id

and dimension_table.name = «Инфраструктура»

and helper_table.distance = 1


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

Проблема медленно меняющихся измерений интересна сама по себе, без усложнения ее иерархичностью классификаторов. В литературе она в большинстве случаев рассматривается в контексте «факт — медленно меняющееся измерение» [7]. Такая задача, действительно, решается относительно просто путем добавления в таблицу измерения даты начала и окончания действия записи. Изменение записи в справочнике приводит к «закрытию» старой записи и добавлению новой.

Возвращаясь к примеру справочника статей затрат, пользователь, желающий получить информацию по актуальной статье затрат на какую-либо конкретную дату, должен включить ее в условие SQL-запроса. Предположим, что справочник статей затрат связан со справочником счетов бухгалтерского учета. Один или несколько бухгалтерских счетов представляют собой статью затрат. Как должно отразиться на справочнике счетов бухгалтерского учета изменение какого-либо атрибута статьи затрат? С одной стороны, с точки зрения плана счетов, изменение атрибута не приводит к изменению сущности статьи затрат и бухгалтерские проводки через план счетов должны относиться на ту же статью. С другой стороны, в справочнике статей затрат появилась новая запись, которая должна быть каким-то образом связана со справочником счетов. Данная проблема может быть решена с помощью разделения таблицы измерений на две — содержащую актуальную информацию и содержащую историю изменения сущности. Этот подход также позволяет решить проблему иерархического измерения с необходимостью поддержания истории изменения записей в нем (рис. 5).



Таблица «dimension_actual» представляет собой таблицу измерений с первичным ключом dimension_id, содержащую корректные атрибуты измерения на сегодняшний день. С ней связана через внешний ключ dimension_id историческая таблица «dimension_history», в которой находится история изменения записей, определяемая датами начала/окончания действия записи (поля date_start, date_end). Актуальная на сегодняшний день запись также присутствует в ней с открытой датой окончания действия. Таблица фактов «fact_table» связана с таблицей измерений через вспомогательную таблицу «helper_table», которая отражает иерархическую структуру измерения.

Важный момент, с которым часто приходится сталкиваться разработчику хранилища данных, связан с агрегатными значениями. Этот класс задач условно можно разделить на два подкласса. Первый рассматривает задачи создания и поддержания агрегатов по имеющимся детальным данным и широко освещен в литературе [8, 11, 12]. Второй связан с тем, что источники данных для хранилища предоставляют собой не детальные значения, а уже некоторый набор агрегированных данных. Такая ситуация типична при создании хранилищ для управляющих компаний и государственных контролирующих органов, собирающих множество отчетных форм.

Крайним случаем такого подхода является модель, которую условно можно назвать «показатель-значение». Суть ее состоит в том, что собирается большой набор показателей, характеризующих финансово-хозяйственную деятельность предприятия. Эти показатели могут быть как связанными между собой функционально, так и нет, могут отражать одни и те же величины, но с разной степенью детализации и т.д. При попытке представить такие данные в виде многомерной модели разработчик сталкивается со значительными проблемами и очень часто идет по пути создания не хранилища данных, а хранилища форм. Типичное хранилище форм строится на основе трех измерений — экономические показатели, время, отчетные формы; таблицы фактов — значения экономических показателей и вспомогательных таблиц, описывающих, как показатели и их значения расположены в отчетных формах.При анализе таких данных аналитик будет испытывать значительные трудности, связанные главным образом с тем, что показатели различных форм нельзя сравнивать между собой. Единственное, что ему остается — это отслеживание изменений показателей одной формы во времени.


Содержание раздела