Агрегаты многомерных кубов OLAP в оперативной памяти

в 3:13, , рубрики: .net, ASP.NET, Business Intelligence, olap, Анализ и проектирование систем, бизнес аналитика, высокая производительность, оперативная память, хранилище данных, метки: , , , , ,

Постановка

Проблематика Business Intelligence решений (Бизнес Аналитика) состоит в предоставлении заинтересованным лицам статистической, аналитической информации по результатам деятельности какого-либо автоматизированного процесса или комплекса процессов.
Например, имеется бизнес процесс фиксации покупок, совершаемых людьми в электронном магазине. В реляционной модели бизнес процесса естественно будут иметься продавцы, покупатели, товар и прочие сущности. При этом, если бизнес процесс успешен, т.е. происходит достаточно интенсивный поток данных, возникают потребности в анализе этих данных для решения различных задач, в том числе экономических. Для финансистов это будет совокупность данных, отражающих:

  • Количество проданного товара за 1-ый квартал текущего года
  • Сумма проданного товара в разрезе продавцов за прошлый год
  • Динамика продаж определенного вида товара в ежемесячном срезе
  • И многие др

При этом, если речь идет о холдинге, в который входят – магазины, рестораны, прочие виды деятельности, то количество данных возрастает, что так же ведет порой и к увеличению видов представлений аналитических данных.
Таким образом перед разработчиком встает проблема по предоставлению максимально широкого, эффективного и удобного инструмента для анализа данных. На помощь приходят OLAP решения, предлагаемые различными брендами, такими как Oracle, SAP, Microsoft, MicroStrategy, Pentaho и многие др.

Заранее хочу сделать несколько оговорок:

  1. В статье предложен метод хранения многопараметрических данных в оперативной памяти без использования специализированных хранилищ (СУБД), служащих основной для решений бизнес аналитики (Business Intelligence)
  2. В статье не пойдет речь об OLAP кубах, принципах их построения в классическом виде MOLAP, ROLAP, HOLAP. Для вводного ознакомления с ними рекомендую следующие статьи:
    habrahabr.ru/post/66356/ — Многомерные кубы, OLAP и MDX
    habrahabr.ru/post/187782/ — Запуск OLAP-сервера на базе Pentaho по шагам
    habrahabr.ru/post/67272/ — Cоздаем OLAP куб. Часть 1
    habrahabr.ru/company/eastbanctech/blog/173711/ — 6 практических советов для начинающих при построении простого BI решения.

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

Проектирование модели

В виду своей деятельности на протяжении последних 3-х лет я занимался созданием бизнес аналитических панелей для предоставления многопараметрических данных конечным пользователям с использованием технологий HTML и таких библиотек как DevExpress, HighCharts, ExtJS. Особенность хранилищ агрегатов – это интенсивное чтение данных и блочное обновление. В рамках работы были испробованы различные виды реляционных моделей данных для хранения агрегатов, однако ни один из этих видов не давал желаемого эффекта – высокая скорость чтения. Это и привело к решению, описанному в данной статье – хранение всех агрегированных данных в оперативной памяти, что влечет за собой следующие задачи:

  • Экономное использование оперативной памяти
  • Эффективные алгоритмы извлечения данных по заданным критериями
  • Хранение и чтение данных из файловых хранилищ

Прежде всего необходимо определить сущности, которыми будем оперировать:

  • Показатель – это именованная сущность, определяемая количественными и качественными характеристиками. Например – «доход» или «расход»
  • Единица измерения – это именованная сущность, определяющая меру, в которой рассчитывается показатель. Например – «доллар» или «рубль»
  • Справочник и элементы справочника – это именованная сущность, определяющая качественные характеристики, связанные с показателем. Например — «Справочник полов», которые содержит в себе элементы «мужской» и «женский»
  • Период – именованная сущность, определяющая временной промежуток времени, за который были сделаны измерения. Например – «год», «квартал», «месяц», «день»
  • Значение – именованная сущность, определяющая агрегированное значение в числовом виде

Можно привести следующие примеры данных, которые должны храниться в хранилище:

  • Показатель «Доход» предприятия, в периоде «2011 год» в разрезе «женского пола» имел значение – 300 «долларов»
  • Показатель «Расход» предприятия, в периоде «1 квартал 2013 года» имел значение – 100 «рублей»

Определив таким образом сущности необходимо определить объектную модель классов, определяющую их взаимосвязь.

Агрегаты многомерных кубов OLAP в оперативной памяти

Как видно из рисунка, в диаграмме классов присутствуют служебные классы, такие как ObjectNameRepository, DataWarehouse. Эти классы удобны в использовании, когда работаешь с коллекциями данных и необходимо определить основные интерфейсы, предоставляющие объекты по заданному правилу.
Класс Index – описывает сущность «Показатель», в который входят такие характеристики, как наименование показателя, атрибуты видимости показателя и прочие атрибуты, необходимые для конкретного приложения. Класс Index включает в себя класс Cube.
Класс Cube – это хранилище качественных характеристик значений показателя и самих значений (иначе Куб данных). Каждый набор характеристик – это точка на пересечении всех измерений куба. Например – если мы имеем куб из 3-х характеристик, таких, например как «вес», «цвет», «размер», то каждая точка – в этом 3-х мерном пространстве будет представлять из себя установленные критерии по каждому из этих измерений. Любой куб данных можно представить в виде двумерной матрицы – где колонками матрицы будут выражены справочники, а строками – заданные характеристики. Например, строка 1 в такой матрице может иметь значения «Вес — 100 кг», «Цвет – красный», «Размер – маленький». Тогда для хранения агрегатов данных – необходимо иметь матрицу, описывающую все возможные комбинации характеристик. При создании такого класса можно использовать два метода оптимизации хранения данных в оперативной памяти:

  • Использовать одномерный массив данных с использованием смещения
  • Использовать битовый массив. В данном случае предлагается анализировать каждую колонку матрицы на ее разнообразие. Например, для колонки «Справочника полов», необходимо всего три значения – «всего», «мужской», «женский». Тогда максимальный объем данных, который может занимать значение в данной колонке – это всего 3 бита. И так для каждого справочника

Класс Cube включает в себя класс Measure, определяющий общую единицу измерения для всего набора качественных характеристик. Это позволяет хранить значения показателей в различных единицах измерения в зависимости от имеющихся характеристик. Т.е. один и тот же показатель в различных кубах может иметь соответствующую кубу единицу измерения. На примере это может быть показатель «Реализовано продукции», который будет измеряться в натуральном выражении – «штука» и в денежном «рубль». В данной статье приводятся только простые виды показателей, единица измерений у которых может быть только одна для одного куба. На практике встречаются такие показатели, единица измерений для которых изменяется в зависимости от качественных характеристик в кубе. Тогда необходимо переходить на новый уровень абстракций, и вводить классы, обслуживающие простые наборы данных и сложные.
Класс Cube так же должен включать в себя сами значения – наборы Value. Т.е. каждый набор характеристик – должен и будет иметь значения, выраженные числом. На это этапе можно применить методы классификации данных, для оптимизации их хранения в оперативной памяти. Например, работая с базой данных и выбирая хранилище или поле для числового значения – в большинстве случаев вы выбираете максимально возможное число с плавающей запятой. Однако это очень ресурсоемко, особенно когда дело касается оперативной памяти. На практике – далеко не все показатели нуждаются в такой точности. Например – показатель «Процент выполнения плана», может нуждаться лишь в целочисленных значениях от 0 до 100. Для которых достаточно и одного байта. Таким образом – можно реализовать предварительный анализ данных по каждому показателю для определения максимально необходимого типа – от BYTE до DECIMAL. Тогда можно уйти на уровень абстракций Value – и породить все от этого класса все необходимые типы для реализации приложения. На практике – эта аналитика дала существенное сжатие данных так, например, при объеме значений в базе данных в 100 миллионов, лишь 5 % из них потребовали тип данных DECIMAL.
При этом при моделировании такого хранилища необходимо реализовать методы сохранения всех данных на жесткий диск и их чтения. Настоятельно рекомендую избегать стандартных сериализатотров и писать собственные на основе BinaryWriter и BinaryReader. А так же рекомендую интенсивно использовать MemoryStream классы. Т.е. процессы чтения и записи на жесткий диск разделить на несколько этапов:

  1. Чтение в поток, находящийся в памяти
  2. Сжатие потока стандартными алгоритмами
  3. Запись потока на жесткий диск

И наоборот:

  1. Чтение с жесткого диска в поток в памяти
  2. Декомпрессия потока
  3. Чтение денных

Такой подход дает возможность оптимизации процесса сжатия и чтения данных с использованием нескольких ядер центрального процессора, не нагружая жесткий диск. Т.е. чтение и запись с жесткого диска выполняется последовательно, а чтение и запись с потоков в памяти – можно распараллелить. Так, на практике – чтение 100 миллионов значений с жесткого диска (примерно 2 ГБ. сжатых данных), и декомпрессия их в памяти и генерация классов (до 35 ГБ) занимает около 5 минут с использованием 32-ядерного сервера Xeon. Извлечение же аналогичных данных из реляционной СУБД занимало порядка 5 суток.
В данной статье не рассмотрены варианты обновления данных в таком хранилище. Но с основной задачей хранилища, такой как – чтение данных данная модель справляется на все 100%. Для обновления данных в таком хранилище необходимо предусмотреть режимы монопольного доступа к памяти. А так же в целях развития системы в виду технических ограничений на оперативную память необходимо развить систему до распределенной оперативной памяти (Sharding).
В данной статье предполагается что процедура агрегации данных происходит во внешней среде и в систему попадают уже агрегаты.
В данной статье так же не приведены коды приложения в виду их тривиальности в особенности в виду использования технологии LINQ, где в большинстве случаев имеют место операции сравнения характеристик на предмет схожести объектов или же их отличий.

Вывод

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

  • Получить значения по «показателю» в заданных «характеристиках» по заданному типу «периода»
  • Получить «остатки» (т.е. все оставшиеся доступные характеристики по показателю) по кубу, когда определены часть «характеристик»
  • Объединить данные нескольких показателей
  • Поиск показателей по заданным характеристикам

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

Автор: Rassul

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js