OLAP.ru   Rambler's Top100
Вы находитесь на страницах старой версии сайта. Перейдите на новую версию OLAP.ru
  
Поиск по сайту
Новости
Основы OLAP
Продукты
Business Objects/ Crystal Decisions
Каталог
OLAP в жизни
Тенденции
Download
Яndex
 
 
 
TopList
 
 Business Objects/Crystal Decisions  Oracle  Microsoft  IBM 
 Hyperion  Sybase  Informix  Actuate  SAS Institute  Brio 

"Подземелья" Oracle Express


Станислав Сидоров
ФОРС, старший эксперт отдела разработки банковских систем
тел. (095) 973-4307

Технология Oracle Express представлена следующими программными продуктами: Express Server/Personal Express - сервер многомерных баз данных; Express Administrator - интерактивное средство описания структуры МБД, проектирования процедур загрузки, загрузки и администрирования данных; Express Analyzer - объектно-ориентированная универсальная система анализа базы данных, хранимой в Express Server/Personal Express; Express Objects - объектно ориентированная среда разработки приложений; Financial Analyzer - система, поддерживающая распределенный бюджетинг, финансовый анализ и экономическое моделирование; Sales Analyzer - система для анализа больших объемов данных, в том числе в хранилищах данных на основе Express Server и RDBMS (см. так же литературу [1]-[3]).

В настоящее время, на мой взгляд, сложилось ошибочное мнение о простоте использования OLAP для разработки систем поддержки принятия решения. Понятие простоты без сомнения можно отнести к процессу использования готового приложения, к процессу исследования многомерной базы данных (МБД) с помощью средств клиентской части приложения, например Express Analyzer. Однако это совсем не относится к процессу разработки приложения. Цель статьи - показать разработчику приложения (именно для этой катагории людей предназначается статья), что его ожидает в процессе разработки, что лежит в "подземельях" Oracle Express. Это не критика и не выискивание слабых или трудных мест, это попытка анализа процесса разработки реального приложения. Предлагаемые в статье рекомендации для решения возникающих проблем не претендуют на "истину в последней инстанции", однако они основаны на реальной практике создания приложения.

Рассматриваемое в статье приложение относится к сфере банковских технологий и предназначено для оценки деятельности банка на основе информации, поступающей от его филиалов. Здесь мы имеем обычную схему развития аналитической системы: от традиционной статической DSS системы, реализованной в виде Oracle-приложения на основе регламентированных запросов, к OLAP-приложению, обеспечивающему динамический многомерный анализ данных, реализованный в технологии Oracle Express [3].

Все проблемы, относящиеся к этапу накопления информации, решаются в рамках Oracle-приложения и не рассматриваются в данной статье.

Для содержательной иллюстрации возникающих задач и способов их решения приведем фрагмент схемы базы данных Oracle-приложения (Рис. 1) и необходимые пояснения, сведенные в таблицу 1.

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

Undisplayed Graphic

Рис. 1 Фрагмент схемы базы данных Oracle-приложения в нотации ERWin.

Таблица 1.
Имя поля Тип данных Правила целостности Назначение
BALANCES - Оборотно-сальдовая ведомость
bal_id number(9) not null, primary key Внутренний идентификатор
bal_dept_kfb varchar2(6) not null, foreign key Код филиала
bal_crrn_2 varchar2(3) not null, foreign key Код валюты
bal_btpe_code varchar2(3) not null, foreign key Код периодичности данных
bal_plan_id number(9) not null, foreign key Код номера счета
bal_tpla_type number(6) not null, foreign key Тип плана счетов
bal_balance_date date not null Дата
bal_input_debet_rest number(25) null Входящий остаток по дебету
bal_input_kredit_rest number(25) null Входящий остаток по кредиту
bal_debet_turnover number(25) null Обороты по дебету
bal_kredit_turnover number(25) null Обороты по кредиту
bal_output_debet_rest number(25) null Исходящий остаток по дебету
bal_output_kredit_rest number(25) null Исходящий остаток по кредиту
bal_proizvodniy varchar2(3) not null Способ получения данных
bal_error varchar2(1) null Наличие ошибок
DEPARTMENS - Справочник филиалов
dept_kfb varchar2(6) not null, primary key Код филиала
dept_dept_kfb varchar2(6) null, foreign key Код дирекции
dept_nfb varchar2(40) not null, foreign key Название

Таблица 1. (продолжение)
Имя поля Тип данных Правила целостности Назначение
PLAN_BALANCES - Справочник номеров счетов
plan_id number(9) not null, primary key Код номера счета
plan_tplan_type varchar2(6) not null, foreign key Тип плана счетов
plan_plan_id number(6) null, foreign key Код номера счета уровня +1
plan_bal_number varchar2(20) not null Номер счета
plan_name varchar2(120) null Наименование счета
CURRENCY - Справочник валют
crrn_code varchar2(3) not null, primary key Код валюты
crrn_short_name varchar2(4) not null Сокращенное название валюты
crrn_name varchar2(80) null Полное наименование валюты
PERIOD_BALANCE_TYPES - Справочник периодичности поступления данных
btpe_code varchar2(3) not null, primary key Код периодичности данных
btpe_short_name varchar2(4) not null Краткое имя периодичности
btpe_name varchar2(80) not null Полное имя периодичности
TYPE_PLANS - Справочник типа плана счетов
tpla_type varchar2(6) not null, primary key Тип плана счетов
tpla_name varchar2(40) not null Наименование плана счетов
tpla_code varchar2(3) null Код плана счетов

Проектирование многомерной базы данных

Логическое представление реляционной базы данных (Рис. 1) имеет вид звездообразной схемы. В соответствии с принятыми рекомендациями (например, см. [1]) внешние ключи таблицы BALANCES становятся размерностями многомерной базы данных (МБД). Естественно добавить к этому еще одну размерность - время, соответствующее дате поступления ОСВ. Обратите внимание, что формат размерности day (число, первые три буквы английского названия месяца, последние две цифры года) не устраивает как по названию месяца, так и по заданию года (конец века уже не за горами). Приведенная ниже последовательность команд Express Language позволяет создать свой формат представления даты:

consider day

vnf '<dd>/<mm>/<yyyy>'

Таблицы DEPARTMENTS и PLAN_BALANCES имеют внешние ключи, ссылающиеся сами на себя, что является естественным признаком наличия иерархической структуры для этих размерностей. Однако в нашем случае имеется несколько отклонений от принятых рекомендаций (без обсуждения корректности нормализации для приведенной схемы базы данных - что имеем, тому и рады). Во-первых, нет необходимости вводить в качестве размерности "Тип плана счетов", который является внешним ключом в таблицах BALANCES и PLAN_BALANCES. Иерархическая структура, хранящаяся в таблице PLAN_BALANCES представляет собой несколько рядом стоящих деревьев, каждое из которых представляет собой отдельный вариант (тип) плана счетов (в рассматриваемой предметной области планом счетов называют иерархический набор счетов, отражающих различные аспекты финансовой деятельности). Таблица PLAN_BALANCES самодостаточна для определения этой структуры, а имя корневого счета отражает тип плана счетов. Во-вторых, в качестве размерности предлагается строка балансового отчета - шесть значений, которые соответствуют шести компонентам ОСВ. В-третьих, из всех возможных вариантов периодичности поступления данных нас интересует только ежедневная. Следовательно, "Периодичность данных" тоже не будет нас интересовать как размерность проектирумой МБД. В таблице 2 сведены все размерности и источники получения информации.

Таблица 2.
Имя размерности Тип данных Источник данных Иерархия Назначение
branch ID таблица departmetns да Филиал
currency ID таблица currency нет Валюта
day Day поле bal_balance_date нет День поступления
gl ID таблица plan_balances да Номер счета
bal_line ID нет Компонента ОСВ

Для окончания первого этапа проектирования нам осталось только сказать, что показатель, определенный на этом множестве размерностей, будем называть bal и он имеет тип данных decimal.

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

Реальное содержание рассматриваемой задачи предполагает наличие двух планов счетов в таблице PLAN_BALANCES: рублевого и валютного. И для первого из них имеет смысл только одно значение валюты - рубли. Таким образом в нашей МБД получается довольно значительный объем, который никогда не будет заполняться и, следовательно, отведенная память будет использоваться не эффективно (на Рис. 2 слева выделена неиспользуемая память).

Для решения этой проблемы разработчики Oracle Espress предлагают метод, основанный на создании размерностей типа Conjoint, объединяющие значения нескольких размерностей. В нашем случае можно создать размерность gl_currency, объединяющую gl и currency. Показатель bal будет теперь определен на размерностях bal_line, branch, day и gl_currency, а при загрузке МБД необходимо предусмотреть выявление и загрузку новых значений размерности gl_currency (т.е. новых сочетаний gl и currency). Из Рис. 2 справа видно, что значения показателя bal определены только для реально имеющихся в таблице BALANCES сочетаний размерностей gl и currency.
Баланс валютный Баланс рублевый gl_currency Вх.Деб
RUR 3974280422525.27 Баланс рублевый RUR 3974280422525.27
USD 1592757926.37 Баланс валютный USD 1592757926.37
NLG 135241.29 Баланс валютный NLG 135241.29
CHF 1429020.46 Баланс валютный CHF 1429020.46
FRF 2652681.06 Баланс валютный FRF 2652681.06
DEM 23527869.93 Баланс валютный DEM 23527869.93
Рис. 2. Наличие данных в МБД: слева - gl и currency разделены, справа - объединены

Для удобства просмотра и анализа (для пользователя совсем не интересны проблемы нашего "подземелья", он должен работать с привычными понятиями) определим формулу вида:

define balance formula decimal <bal_line branch day gl currency>

EQ

bal

Эта формула разделит размерность gl_currency на привычные составляющие, а все вместе позволит нам более экономно использовать память. Однако если в одном месте что-то добавится, то в другом обязательно что-то исчезнет. Так агрегирование данных по иерархии размерности gl в этом случае не столь очевидно (возможности агрегирования мы будем обсуждать немного позднее).

Undisplayed Graphic

Рис. 3. Создание размерности bal_line.

Кроме того для удобства просмотра и анализа данных все равно придется создавать формулы отдельно для каждого плана счетов. Эти аргументы в конечном счете привели к следующей итерации в проектировании МБД и размерность gl была разделена на две gl_rub и gl_val отдельно для рублевого и валютного планов счетов. Соответственно были введены два показателя bal_rub и bal_val вместо bal, в которых размерность gl заменена соответственно на … gl_rub и gl_val, причем первый перестал зависеть от размерности currency. Весь процесс создания перечисленных объектов МБД возможен в окне Personal Espress (Express Server) для чего используется команда define в различных модификациях (см. пример создания формулы balance). Однако более удобным и наглядным этот процесс можно сделать используя Express Administrator. На Рис. 3 приведен пример окна определения размерности bal_line.

Undisplayed Graphic

Рис. 4. Ввод данных для размерности bal_line

Загрузка многомерной базы данных

Загрузку данных в МБД естественно начинать с загрузки значений размерностей. В таблице 2 приведены источники информации для выбранных в нашем случае размерностей. Заметим, что размерность bal_line не имеет внешних источников данных и вполне можно ограничиться окном редактирования Express Administrator для непосредственного ввода значений (см. Рис 4).

Undisplayed Graphic Undisplayed Graphic

Рис. 5. Формирование программ загрузки для размерности branch

Остальные размерности имеют источники данных в БД Oracle и требуют формирования программ загрузки данных в МБД. В Express Administrator для создания таких программ предусмотрено специальное средство, которое использует ODBC для доступа к Oracle. Во многих случаях полученная таким образом программа совсем не требует доработки. Рассмотрим этот процесс сначала на примере создания программы загрузки размерности branch. На Рис. 5 приведено окно Import SQL Data в котором устанавливается соответствие колонок таблицы Oracle и объектов МБД (столбец Express Object), заполнение этого столбца осуществляется простым перемещением мышкой названий этих объектов из схемы МБД. В нашем случае колонке dept_kfb поставлена в соответствие размерность branch, а dept_nfb - переменная b4.shortlabel, где хранится имя филиала. Express Administrator по кнопке Save генерирует и запоминает в БД программу заполнения размерности значениями из БД Oracle. Процесс заполнения данных для размерности branch еще не закончен, т.к. это иерархическая размерность и требуется установить взаимосвязь объектов на различных уровнях иерархии. Обратите внимание, что использование признака Hierarchical в окне Define Dimension автоматически приводит к созданию объектов типа Relation (Отношение) для поддержки этой возможности. В нашем случае это b4.parent, для заполнения которого используется колонка dept_dept_kfb (см. Рис. 5 правый).

Полученные в результате работы Express Administrator программы в данном случае не требуют никакой доработки и могут использоваться для загрузки значений размерности branch и определения иерархии ее объектов. Аналогичным образом могут быть получены программы загрузки для оставшихся размерностей. Однако мы пойдем другим путем.

Естественную последовательность загрузки: сначала значения размерностей, а затем показателей, определенных на них, не следует понимать буквально. Если при загрузке значений размерностей использовать полностью все значения соответствующих справочников, многомерный куб может оказаться очень разреженным. Очевидно, что не все значения справочников PLAN_BALANCES и CURRENCY используются банком в реальной эксплуатации в силу естественной ограниченности сферы деятельности. Однако в отличии от Oracle-приложения, где количество строк в справочниках мало влияло на размер таблицы BALANCES, в МБД место отводится для всех возможных значений всех сочетаний размерностей.

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

Во-первых, у нас совсем нет объектов МБД для колонок таблицы BALANCES, содержащих различные варианты дебета и кредита. Вернее объект один (bal_rub или bal_val), а разным колонкам соответствуют различные значения размерности bal_line. Такой вариант соответствия объектов не может быть установлен с помощью окна Import SQL Data. Во-вторых, таблица BALANCES содержит значения и рублевого и валютного плана счетов, таким образом необходимо включение конструкции where для колонки bal_tpla_type в текст запроса на SQL. В-третьих, необходимы конструкции where для условия ежедневной периодичности поступления данных (bal_btpe_code='0'), способа получения данных (bal_proizvodiy='Пер'), отсудствия ошибок (bal_error='*'). И, наконец, мы хотели бы получить программу с датой поступления данных в качестве аргумента, что то же требует конструкции where.

Все сказанное неизбежно приводит нас к необходимости ручной корректировки программы загрузки. Приведем фрагменты программы загрузки показателя bal_val, которые после корректировки будут выглядеть следующим образом (ключевыми здесь являются фрагменты sql declare для определения курсора и sql Fetch для организации цикла выборки данных из БД Oracle):

" Дополнительный аргумент

arg _cur_day date

" Дополнитльные переменные

vrb _branch ID

vrb _currency ID

vrb _day ID

vrb _gl_val ID

vrb _in_deb decimal

vrb _in_cred decimal

vrb _tur_deb decimal

vrb _tur_cred decimal

vrb _out_deb decimal

vrb _out_cred decimal

" Определение курсора с учетом перечисленных

" дополнительных требований

sql declare C1 cursor for -

select -

BAL_DEPT_KFB, -

BAL_CRRN_2, -

BAL_BALANCE_DATE, -

BAL_PLAN_ID, -

BAL_INPUT_DEBET_REST, -

BAL_INPUT_KREDIT_REST, -

BAL_DEBET_TURNOVER, -

BAL_KREDIT_TURNOVER, -

BAL_OUTPUT_DEBET_REST, -

BAL_OUTPUT_KREDIT_REST -

from BALANCE.BALANCES -

where bal_error = 'N' -

and bal_proizvodniy = 'Пер' -

and bal_btpe_code= '0' -

and bal_tpla_type ='ВАЛЮТН' -

and BAL_BALANCE_DATE = :_cur_day

" Цикл чтения информации

while SQLCODE eq 0

do

"******************************

" Fetch the rows

"******************************

_i = _i + 1

sql Fetch C1 into -

:_branch -

:_currency -

:_day -

:_gl_val -

:_in_deb -

:_in_cred -

:_tur_deb -

:_tur_cred -

:_out_deb -

:_out_cred

lmt branch to _branch

" Дозагрузка размерности currency

mnt currency merge _currency

lmt currency to _currency

" Дозагрузка размерности day

mnt day merge _day

lmt day to _day

" Дозагрузка размерности gl_val

mnt gl_val merge _gl_val

lmt gl_val to _gl_val

bal_val(bal_line 'IN_DEB') = _in_deb

bal_val(bal_line 'IN_CR') = _in_cred

bal_val(bal_line 'TUR_DEB') = _tur_deb

bal_val(bal_line 'TUR_CR') = _tur_cred

bal_val(bal_line 'OUT_DEB') = _out_deb

bal_val(bal_line 'OUT_CR') = _out_cred

.....

doend

upd

Обратите внимание, что после работы этой программы будут добавлены только значения размерностей, однако в нашем случае каждому значению размерности соответствует сокращенное и полное наименование, а gl_rub и gl_val имеют кроме того иерархическую структуру. Все это требует заполнения соответствующих объектов МБД, создания и выполнения предназначенных для этого программ загрузки. Процесс создания этих программ аналогичен уже рассмотренным для размерности branch. Полученные программы пригодны для использования без всякой доработки и должны выполняться после загрузки очередной порции строк ОСВ.

Следует отметить, что процесс разработки программ загрузки данных может быть существенно упрощен, если использовать view, построенные на исходных таблицах Oracle-приложения специально для использования при загрузке МБД.

Агрегирование данных

Важным и без сомнения очень привлекательным является наличие в продуктах Oracle Express средств выполнения операций агрегирования данных. Для агрегирования возможны две стратегии - первая предполагает выполнение этой операции в процессе просмотра данных ("на лету") с использованием Express Analyzer или других средств клиентской части приложения. Этот процесс требует некоторых временных затрат, однако он вполне приемлем для агрегирования в пределах заданного диапазона по какой-либо размерности.

Вторая стратегия предусматривает запись результатов агрегирования непосредственно в МБД вместе с другими данными и на мой взгляд более подходит для агрегирования по иерархическим размерностям. Это позволяет в дальнейшем использовать рассчитанные результаты без дополнительных временных затрат. Затратами памяти в этом случае можно пренебречь, т.к. соответствующее место в многомерном кубе все равно уже отведено (впрочем организация памяти на диске предусматривает пропуск страниц, целиком содержащих неопределенные значения показателя).

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

arg _day text

lmt day to _day

lmt branch to all

lmt bal_line to all

lmt gl_rub to all

rollup bal_rub over branch using b4.parent

upd

Команда rollup выполняет обычное суммирование по выбранной размерности и результаты суммирования проставляет для тех значений размерности, у которых есть подчиненные (потомки). Однако это естественно не единственный метод агрегирования, который может быть применен к данным. В рассматриваемом нами приложении очень актуальным является агрегирование по временному интервалу, например по месяцу. В этом случае применяются различные алгоритмы агрегирования для различных компонент строки ОСВ. Для оборотов - это обычное суммирование, для входящего остатка по дебету и кредиту - выбор значения за минимальную дату временного интервала, для исходящего остатка по дебету и кредиту - выбор значения за максимальную дату временного интервала:

tempstat day

do

limit day to month

" Суммирование оборотов по дебету и кредиту

if bal_line EQ 'TUR_DEB' OR bal_line EQ 'TUR_CR'

then return TOTAL(bal_rub gl_rub bal_line branch)

" Выбор значения за минимальную дату временного

" интервала для входящего остатка по дебету и кредиту

if bal_line EQ 'IN_DEB' OR bal_line EQ 'IN_CR'

then return bal_rub(day begindate(bal_rub))

" Выбор значения за максимальную дату временного

" интервала для исходящего остатка по дебету и кредиту

if bal_line EQ 'OUT_DEB' OR bal_line EQ 'OUT_CR'

then return bal_rub(day enddate(bal_rub))

doend

Следует добавить несколько слов об агрегировании по размерности типа Conjoint. Суть дела состоит в том, что выполнение команды rollup по базовой размерности, входящей в состав размерности типа Conjoint, возможна только начиная с Oracle Express 6.0 (напомню, что в нашем случае иерархическая размерность gl входила в состав размерности gl_currency). Для версии 5.0 требуется создание и заполнение еще одного отношения, построенного на размерности gl_currency, а затем выполнения rollup уже с учетом этого отношения. Учитывая, что поставка версии 6.0 уже начинается, не будем останавливаться на этой проблеме более подробно, а заинтересованные могут обратиться к автору за дополнительными материалами.

Реляционный OLAP (ROLAP)

Появление термина Реляционный OLAP в качестве самостоятельного связано с тем, что исторически сложилось так, что сегодня OLAP подразумевает не только многомерный взгляд на данные со стороны конечного пользователя, но и многомерное представление данных в БД [3]. Все что мы рассматривали выше основывалось на предположении, что данные для анализа загружаются в МБД и именно МБД Oracle Express является хранилищем всей информации. Однако средства Oracle Express позволяют организовать динамическую связь с данными, расположенными непосредственно на Oracle-сервере. Это взаимодействие реализуется с помощью создания формул специального вида. Простой и наглядный способ создания таких формул обеспечивает Express Administrator.

В окне Define a Formula (см. Рис. 6 справа) необходимо установить признак SQL Data. По кнопке Map Data раскрывается окно Map Data (см. Рис. 6 слева), в каждой строке столбца Express Object имеется List Box, элементы которого составляют наименования размерностей, определенных для формулы (в нашем случае это branch, day_txt и gl_rub), и специальный элемент data variable для определения результата вычисления формулы. Когда всем элементам списка List Box поставлены в соответствие колонки таблицы Oracle, Express Administrator по кнопке OK генерирует текст формулы в окне Equation. Ниже приведен текст формулы для динамического получения одной из компонент ОСВ:

if PRO_OLAP_CACHE2 eq XP_NULL then NA

else nafill(PRO_OLAP_CACHE2, XP_SQLGen('BLR_IN_CR',

convert(BRANCH, text)

convert(DAY_TXT, text)

convert(GL_RUB, text) ))

Undisplayed Graphic Undisplayed Graphic

Рис. 6. Создание формулы для динамической связи с Oracle-сервером

Сделаем несколько комментариев, поясняющих полученный результат:

• функция XP_SQLGen, реализующая доступ к данным на Oracle-сервере через ODBC, хранится в служебной базе данных xpddcode.db, текст ее не доступен и всякую корректировку полученного текста следует проводить крайне осторожно;

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

• в процессе создания формулы Express Administrator создает два новых объекта: размерность типа Conjoint, объединяющую все перечисленые в формуле базовые размерности, и переменную, определенную на этой размерности (в нашем случае PRO_OLAP_CACHE2). Эта переменная служит буферной памятью (cache) для хранения данных, полученных из Oracle-сервера, а наша формула является чем-то вроде определенной выше формулы balance, которая использовалась для разделения размерностей gl и currency;

• для создания формулы очень хорошо использовать заранее подготовленные view. В нашем приложении это упрощает применение конструкции where для отбора необходимых ОСВ из таблицы BALANCES;

• использование view позволяет избежать последствий не совсем корректной работы функции XP_SQLGen с данными Oracle типа date. В рассматриваемом приложении - это поле bal_balance_date и соответствующая ему размерность day. Для корректной реализации динамического доступа к данным при создании view было сделано преобразование даты в текстовое поле по формату 'dd/mm/yyyy', что соответствует размерности day. И, наконец, необходимо создать еще одну размерность (day_txt) типа text для хранения даты в текстовом виде. Именно эта размерность была использована при создании формулы;

• без использования view формула позволяет извлекать только одно из шести значений ОСВ (входящий остаток по дебету в нашем случае). Таким образом для получения полной строки ОСВ неоходимо создать шесть таких формул и еще одну для получения привычной конструкции типа bal_rub или bal_val. Использование view с новыми колонками, например bal_line_name и bal_line_value позволит создать формулу, решающую задачу в общем виде;

• завершающим моментом, который позволит пользователю работать только с одним объектом МБД независимо от источника данных, будет создание формулы, объединяющей переменную bal_rub (bal_val) и формулы динамического доступа.

Завершая обсуждение средств динамического доступа к данным Oracle-сервера следует обратить внимание на два момента. Во-первых, очень проблематичным является возможность использования rollup для данных, полученных таким образом. Дело в том, что объектом МБД в этом случае является формула, для которой эта возможность бессмыслена, а реальным хранилищем данных служит cache, которая используется только временно и определена она на размерности типа Conjoint. Во-вторых, в качестве стратегии использование динамического доступа к данным Oracle-сервера очень привлекательно выглядит разделение данных по уровням иерархии. Агрегированные данные верхних уровней иерархии хранятся в Oracle Express, а более детальные и, следовательно, более объемные - на Oracle-сервере. Проиллюстрируем эту стратегию на примере нашего приложения. Введем вместо размерности day размерность time, которая будет иметь три уровня иерархии: год, месяц и день. Логично загружать в МБД верхние два уровня, а при необходимости получения более детальной информации динамически связываться с Oracle-сервером. В приведенном ниже примере ora_bal_rub_day - функция, реализующая динамический доспуп к Oracle, а bal_rub_mon - переменная МБД, содержащая агрегированные данные за месяц и год.

if t2.levelrel(t2.hierdim 'STANDARD') eq 'L3'

then ora_bal_rub_day

else bal_rub_mon

Однако time это не единственная размерность, имеющая иерархическую структуру, еще есть gl и branch, для которых агрегирование необходимо будет проводить непосредственно на Oracle-сервере. В нашем случае Oracle-приложение обладает такими возможностями (свойства DSS системы, как уже говорилось были заложены), однако понятно, что это возможно сделать не всегда.

Дальнейшее развитие приложения

Созданная в результате описанной разработки БД приложения служит надежной основой для его дальнейшего развития. Строки ОСВ - это тот фуднамент, на котором основаны многие методы аналитических исследований состояния банка. В работе [4] содержится описание методики анализа финансового состояния банка по набору показателей, рассчитываемых на основе различных компонент плана счетов. Расчет каждого из этих показателей реализуется с помощью несложной программы и может быть вполне выполнен средствами клиентской части приложения, например средствами Castom Measures в Express Analyzer.

Для вычисления показателей пользователю необходимо проводить несложные расчеты с элементами многомерного куба balcons (это некоторое обобщение bal_rub и bal_val, приведенное к одной валюте и определенное на множестве размерностей, совпадающих с bal_rub). Примером такого элемента является исходящий остаток по дебету счета 03, а соответствующее выражение может быт записано в виде: balcons(bal_line 'OUT_DEB', gl_rub '98276'). Если 'OUT_DEB' каким-то образом ассоциируется с исходящим остатком по дебету, то '98276' уже совсем никак, т.к. это код номера счета, который был извлечен из поля plan_id таблицы PLAN_BALANCES. Этому полю в той-же таблице соответствует plan_bal_number, для которой при загрузке в МБД мы определили переменную g3.shortlabel, связанную с размерностью gl_rub. Именно в ней и содержится номер счета 03. Выражение, которое извлекает его код, будет выглядеть следующим образом:

limit(gl_rub to g3.shortlabel(pro_olap.langdim 'ENU') EQ '03')

Очевидно, что для так называемого конечного пользователя эта фраза слишком сложна. Упростить ее можно, если заготовить программу извлечения кода номера счета по его номеру:

arg _shortname text

return limit(gl_rub to g3.shortlabel(pro_olap.langdim 'ENU') EQ _shortname)

С учетом этой и аналогичной программы для размерности bal_line исходное выражение можно записать в виде:

balcons(bal_line get_bal_line_cod('Исх.Деб'), gl_rub get_gl_rub_code(03))

что вполне доступно для понимания и использования.

Следует отметить, что набор показателей в свою очередь имеет иерархическую структуру и вполне подходит в качестве еще одной размерности МБД (назовем ее anal) и в конечном счете нам хотелось бы создать формулу, реализующую новый многомерный куб на основе размерностей branch, day и anal, однако средства клиентской части приложения такими возможностями не обладают и снова нам надо опускаться в наше "подземелье". Схема уже во многом известна: создание новой размерности, загрузка данными самой размерности и связанных с ней объектов (имена и структура иерархии), определение формулы расчета различных показателей.

Загрузку данных, связанных с этой размерностью, было предложено сделать из обычного текстового файла для чего в Express Administrator предусмотрены средства генерирования программы загрузки аналогичные тем, что рассматривались для загрузки данных из Oracle. Однако файл, подготовленный в Notepad, после загрузки превратил родные русские буквы в названиях показателей во что-то совсем на них не похожее. Поправить ситуацию удалось только после того, как для переменной a1.longlabel, содержащей наименование показателя, было выполнено следующее преобразование:

a1.longlabel = translate(a1.longlabel,tooem)

Об этой возможности функции translate рассказал автору сотрудник Oracle CIS Роман Самохвалов правда совсем по другому, но очень существенному поводу (об этом может быть в другой раз).

Несмотря на то, что желаемого результата удалось достигнуть без дополнительных затрат дискового пространства для хранения вычисленных показателей, такой способ решения может повлечь за собой значительные временные затраты. Альтернатива - создать переменную, определенную на размерностях branch, day и anal, и дополнить процесс загрузки еще одной программой агрегирования с учетом выбранных показателей и записью результата в МБД. Как известно проблема компромисса между временем и памятью постоянно преследует разработчиков программного обеспечения. Oracle Express в этом случае не исключение, а скорее обострение этой проблемы.

Созданная МБД может служит основой для прогнозирования развития банка. Oracle Express позволяет осуществлять такой погноз с помощью команды forecast. Приведенная ниже программа позволяет построить линейный прогноз рублевого баланса на основе временного интервала, определенного аргументами _s_day и _e_day, на _len следующих временных интервалов.

arg _s_day date

arg _e_day date

arg _len integer

lmt branch to all

lmt bal_line to all

lmt gl_rub to all

lmt day to _s_day to _e_day

for branch

do

for bal_line

do

for gl_rub

do

forecast length _len, fcname bal_rub_fcst, time day, bal_rub

doend

doend

doend

Благодарности.

Хочу отметить, что в моей работе большую помощь оказали сотрудники Oracle CIS Дмитрий Гусев (уже бывший) и Роман Самохвалов. Роман кроме того высказал полезные замечания и советы уже по матералу самой публикации.

Литература.

1. Проектирование многомерной базы данных для OLAP. Д. Меннингер. ORACLE Magazine/RE, № 1, 1996

2. Принципы проектирования и использования многомерных баз данных (на примере Oracle Express Server). А.А.Сахаров. СУБД, № 3,1996

3. Концепции построения и реализации информационных систем, ориентированных на анализ данных. А.А.Сахаров. СУБД, № 4,1996

4. Прибыльность и ликвидность: анализ финансового состояния банка. И.А.Аргунов. Банковский журнал №3,1995

 Обсудить на форуме   Написать вебмастеру 

© 2001 Interface Ltd