Показаны сообщения с ярлыком essbase. Показать все сообщения
Показаны сообщения с ярлыком essbase. Показать все сообщения

23 нояб. 2010 г.

XREF vs Partitions

Наверное на каждом проекте мы сталкиваемся с необходимостью обмениваться данными между кубами. Для этого в Essbase есть специальные инструменты: XREF, Replicated Partition, Transparent Partition.

Рассмотрим их по порядку.

XREF - cамый простой и безболезненый способ получить данные из другого куба, минусы - это низкая производительность и проблемы с созданием блоков (в 11.1.2 добавили @XWRITE). Не рекомендую использовать XREF в формулах динамических элементов (Dynamic Calc) т.к. на больших срезах это приводит к потере производительности.
Пример использования: получить значение по ограниченному срезу.

Replicated partition -  если вам надо копировать блоки нижнего уровня 1:1 без всяких расчетов и транформаций, то что надо. Есть функциональность по переносу только обновленных данных.
Пример использования: передать данные по статье A по нижнему уровню из Source в Target.

Дополнительная информация - http://essbase.ru/2010/10/replicated-partitions/

Transparent partition - мощный инструмент для маштабирования. Если сравнивать с Oracle RDB - это аналог view или updateable view. Имеет ряд особенностей связанных с тем, что данные не хранятся в Target кубе, а подтягиваются налету. Пример: в Target по данным из партиции невозможно создать блоки, выгрузить данные с помощью Dataexport и т.д. Но что очень интерестно - из Target можно обновлять данные в Source!
Пример использования: разделение приложения на Факт и План с партицией по сценарию, разделение по странам, версиям и т.д.

Дополнительная информация - http://essbase.ru/2010/10/transparent-partition/

Сравнительная таблица:

* в 11.1.2 добавлена функция @XWRITE, которая позволяет записывать данные в Target
** данные изменяются только после запуска обновления партиции или вызова XREF
*** write-back функциональность

Пример MaxL создание Replicated partition и ее обновление:
create or replace replicated partition 'RP_ACT'.'RP'
area '"ACT"' sourcearea1
to 'RP_BUD'.'RP'
area '"ACT"' targetarea1;

refresh replicated partition RP_ACT.RP to RP_BUD.RP at 'localhost' all data;

refresh replicated partition RP_ACT.RP to RP_BUD.RP at 'localhost' updated data; 

P.S. Выгрузка и загрузка данных с помощью Dataexport, Report script, MDX в данном случае не рассматривались
P.S.S. Source - это куб источник. Target - куб получатель данных.
P.S.S.S. Если производительности XREF не хватает, смотрите в сторону партиций. Если партиции не устраивают, то используйте Dataexport

10 нояб. 2010 г.

Берегись пустых блоков

Агрегирует ли Essbase пустые блоки? Сейчас узнаем.

1. Очищаем куб Sample.Basic и смотрим количество существующих блоков:
2. Вводим число 1.
3. Меняем 1 на #Missing
4. Смотрим количество существующих блоков:
  • Existing level 0 blocks - 1
  • Existing upper-level blocks - 0
5. Запускаем скрипт агрегации:

     SET AGGMISSG ON;
     CALC ALL;

6. Смотрим количество существующих блоков:
  • Existing level 0 blocks - 1
  • Existing upper-level blocks - 8!!!

Вывод - независимо от того есть ли данные в какой-либо ячейке или нет Essbase агрегирует данные (создает блоки верхнего уровня), что приводит к увеличению времени расчета и увеличению размера БД.

Что делать - удалить пусты блоки можно командой "CLEARBLOCK Empty;"

Как еще бороться с ненужными данными:
  • Удаляйте нули (часто пользователи вместо #Missing вносят "0")
  • Правильно удаляйте ненужные срезы командами CLEARBLOCK или CLEARDATA (не фиксируйте плотные элементы).
  • Выгружайте нулевой срез в реляционную таблицу и анализируйте данные (часто много ненужных цифр залипают на Begbalance, архивных статьях и т.д.)

P.S. Еще один пример скрипта и его краткого лога, где агрегация работает неэффективно
/* параметр логировая */
SET MSG SUMMARY;

/* удаляем все блоки*/
CLEARBLOCK ALL;

/* создаем один блок c Jan = 100*/
SET CREATENONMISSINGBLK ON;
FIX ("New York",    "100-10",    "Sales", "Actual")
    "Jan" = 100;
ENDFIX
SET CREATENONMISSINGBLK OFF;

/* агрегируем Feb */
SET AGGMISSG ON;
FIX ("Feb")
   CALC DIM ("Measures", "Product", "Market", "Scenario");
ENDFIX
/* удалили */
Clearing all data blocks from [(ALL)] partition
Removed [9] data blocks

/* создали один блок */
Calculating [ Year(Jan)] with fixed members [Sales; 100-10; New York; Actual]
Create Blocks on Equations: [Enabled]
Create Non #Missing Blocks: [Enabled]
Total Block Created: [1.0000e+000] Blocks

/* создали 7 блоков */ 
Calculating [ Measures, Scenario, Product, Market, with fixed members [Year(Feb)]
Aggregate #Missing values:  [Enabled]
Total Block Created: [7.0000e+000] Blocks
Я сделал запись в Jan, а агрегировал по Feb - все равно блоки создаются. Это конечно же не ошибка, а особенность работы Essbase, которую надо учитывать.

24 окт. 2010 г.

Dynamic Calc Members (BSO)

Когда же лучше всего использовать динамические элементы в BSO-кубах?


1. Плотные (dense) измерения

Использовать нужно всегда т.к. это ведет к уменьшению размера блока => размер куба будет меньше => производительность расчетов улучшится, производительность извлечения данных (retrieve) меняется незначительно +/- 1%! Необходимо только избегать динамических элементов с комплексными формулами т.е. когда при расчете формулы необходимо смотреть в другие блоки. Кандидаты на изменения типа храния на динамический - родители или любой элемент с простой формулой.

Примеры (Период и Статья - плотные, Страна - разряженные):
  • Кварталы (Q1, Q2, Q3, Q4)  - можно сделать динамическими
  • (+) Acc_Total: Выручка итого
        (+) Acc_01: Выручка A
        (+) Acc_02: Выручка Б
    Статью Acc_Total можно сделать динамической
  • Статья: Prof_01 = Acc_01 / Acc_Total - можно сделать динамической (расчет в пределах одного блока)
     
  • Статья: Prof_Russia =  Acc_Total->Entity_Russia - нужно делать хранимой т.к. при распаковке любого блока (расчете или просмотре) Essbase будет смотреть на блок по стране Entity_Russia


2. Разряженные (sparse) измерения

Использовать  можно только для уменьшения времени агрегации, при этом ухудшается время извлечения данных (retrieve).

Пример:
  • (+) Entity_Russia - dynamic
        (+) Entity_Msc - store
        (+) Entity_Spb - store
    Если пользователь строит запрос по Entity_Russia, то серверу необходимо прочитать 2 дополнительных блока по Msc и Spb
Когда не нужно делать динамическими плотные элементы:
  • Когда элемент участвует в выгрузках (report script, dataexport)
  • Когда элемент участвует в партициях
  • Когда элемент участвует в создании блоков (datacopy с динамических элементов не работает)
  • Когда на элементе хранят расчетные данные (аллокации, элиминации)

3. Выводы

Динамические элементы - это хорошая возможность улучшить производительность, но конечно же со своей спецификой.

15 окт. 2010 г.

История одной оптимизации

Часть 1. Как было настроено до оптимизации

Настройки Essbase.cfg
...
CALCCACHEHIGH    200000000 
CALCCACHEDEFAULT 50000000 
CALCCACHELOW     10000000
...

Порядок измерений (песочные часы):

Dimension                    Type    Declared Size  Actual Size
=============================================
Account                          DENSE   809            785
Period                             DENSE   20               18
Currency Rates               SPARSE  6                  5
Scenario                         SPARSE  7                  6
SparseDimA                   SPARSE  8                  6
Years                             SPARSE  8                  7
Currency                        SPARSE  10                8
Version                          SPARSE  15               15
SparseDimB                  SPARSE  17                13
SparseDimC                  SPARSE  125            122
SparseDimD                  SPARSE  125            124
Entity                             SPARSE  198            196
SparseDimE                  SPARSE  199            197
SparseDimF                  SPARSE  288            144

Скрипт агрегации:
SET CACHE ALL;
SET CACHE HIGH;
SET AGGMISSG ON;
SET UPDATECALC OFF;
SET FRMLBOTTOMUP ON;
SET MSG SUMMARY;
SET LOCKBLOCK HIGH;
SET EMPTYMEMBERSETS ON;

FIX(InputValue, FY10, RUR, Work, Budget)

       CALC DIM (Account, Period, SparseDimA, SparseDimB...)

ENDFIX

Часть 2. Что получилось улучшить

1. Сделал динамическими родителей в измерениях Period и Account  +25%

      Размер блока:
  • было  Account(785) х Period(18) х 8байт =  113040
  • стало  Account(705) х Period(13) х 8байт = 73320 (~уменьшился на 30%)

    P.S. Не делайте динамическими dense элементы с комплексными формулами (есть ссылка на другой блок)

2. Изменил порядок измерений +15%:
  • Dense - от большего к меньшему
  • Sparse - от меньшего агрегируемого к большему, неагрегируемые измерения, большие плоские измерения для паралельных вычислений

Dimension                    Type    Declared Size  Actual Size
=============================================
/* Dense от большего к меньшему */
Account                          DENSE   809            705
Period                             DENSE   20               13
/* Агрегируемые */
SparseDimC                  SPARSE  125            122
SparseDimD                  SPARSE  125            124
SparseDimE                  SPARSE  199            197
SparseDimA                  SPARSE  8                  6
SparseDimB                  SPARSE  17                13
/* Прочие (неагрегируемые) измерения */
Currency Rates               SPARSE  6                  5
Scenario                         SPARSE  7                  6
Years                             SPARSE  8                  7
Currency                        SPARSE  10                8
Version                          SPARSE  15               15
/* Измерения для параллельных расчетов */
Entity                             SPARSE  198            196
SparseDimF                  SPARSE  288            144

    P.S. Измерения  SparseDimA и SparseDimB логичнее поставить выше, но на них не хватит CalcCache, поэтому эти измерения перемещены ниже
    P.S.S. Какие sparse измерения необходимо переместить вниз, а какие вверх определяется только опытным путем т.е. тестируем-тестируем-тестируем

3. Включил параллельные вычисления +40%

    SET CALCPARALLEL 4;
    SET CALCTASKDIMS 2;

4. Расчитал Calculator Cache +5%
   SparseDimC (122) х SparseDimD(124) х SparseDimE (197) х 8байт / 1024 = 23 282 кб

Изменения в essbase.cfg
...
CALCCACHEHIGH    200000000 
CALCCACHEDEFAULT 50000000 
CALCCACHELOW     25000000
...


5. Изменил скрипт агрегации +50%

SET CACHE ALL;
SET CACHE LOW; /* 25Мб */;

SET AGGMISSG ON;
SET UPDATECALC OFF;
SET FRMLBOTTOMUP ON;
SET MSG SUMMARY;
SET LOCKBLOCK HIGH;
SET EMPTYMEMBERSETS ON; 

SET CALCPARALLEL 4;
SET CALCTASKDIMS 2;
/* WaterFall agreggetion */ FIX(InputValue, FY10, RUR, Work, Budget, @RELATIVE(YearTotal,0)) /*main*/ FIX(@RELATIVE(&vEntity,0)) FIX(@RELATIVE(SparseDimA,0)) FIX(@RELATIVE(SparseDimB,0)) FIX(@RELATIVE(SparseDimC,0)) FIX(@RELATIVE(SparseDimD,0)) FIX(@RELATIVE(SparseDimE,0)) FIX(@RELATIVE(SparseDimF,0)) CALC DIM (Account); ENDFIX FIX(@DESCENDANTS(Account)) AGG(SparseDimF); ENDFIX ENDFIX /*SparseDimF*/ FIX(@DESCENDANTS(Account) @DESCENDANTS(SparseDimF)) AGG(SparseDimE); ENDFIX ENDFIX /*SparseDimD*/ FIX(@DESCENDANTS(Account) @DESCENDANTS(SparseDimF) @DESCENDANTS(SparseDimE)) AGG(SparseDimD); ENDFIX ENDFIX /*SparseDimC*/ FIX(@DESCENDANTS(Account) @DESCENDANTS(SparseDimF) @DESCENDANTS(SparseDimE) @DESCENDANTS(SparseDimD)) AGG(SparseDimC); ENDFIX ENDFIX /*SparseDimB*/ FIX(@DESCENDANTS(Account) @DESCENDANTS(SparseDimF) @DESCENDANTS(SparseDimE) @DESCENDANTS(SparseDimD) @DESCENDANTS(SparseDimC)) AGG(SparseDimB); ENDFIX ENDFIX /*SparseDimA*/ FIX(@DESCENDANTS(Account) @DESCENDANTS(SparseDimF) @DESCENDANTS(SparseDimE) @DESCENDANTS(SparseDimD) @DESCENDANTS(SparseDimC) @DESCENDANTS(SparseDimB)) AGG(SparseDimA); ENDFIX ENDFIX /*Entity*/ FIX(@DESCENDANTS(Account) @DESCENDANTS(SparseDimF) @DESCENDANTS(SparseDimE) @DESCENDANTS(SparseDimD) @DESCENDANTS(SparseDimC) @DESCENDANTS(SparseDimB) @DESCENDANTS(SparseDimA)) @IDESCENDANTS(&vEntity, -1); @ANCESTORS(&vEntity); ENDFIX ENDFIX /*main*/

Часть 3. Не забываем про стандартные рекомендации

    - ACR (Average clustering Rate) должен стремится к  1, для этого запускайте dense реструктуризацию
    - Размер блока должен быть между 10 и 100KB (может быть больше для 64 bit essbase)
    - Data cache должен быть около 12.5% от общего размера pag файлов
    - Index cache должен быть таким же как ind файлы
    - В одном приложение только 1 куб

19 авг. 2010 г.

Essbase Custom-Defined Macros

Задача:
Существует куб со следующими измерениями:
Account
   Acc1
   Acc2
   Acc3
Period
   YearTotal
     Q1
       Jan
       Feb
       ...
Year
   FY09 
   FY10
   FY11

Необходимо создать функцию XXPRIOR которая умеет "перескакивать" через год т.е.

XXPRIOR(Jan->FY10) = Dec->FY09

Решение:
Создаем макрос в MaxL:
create or replace macro '@XXPRIOR' 
(SINGLE) as 
'( 
  (@ISMBR(Jan) * @@1->Dec->@CURRMBRRANGE("Years", LEV, 0, -1,-1))  
    + (@ISMBR(Feb:Dec) * @PRIOR (@@1)) 
)'

Перестартовываем приложение в Essbase.

Используем макрос в calc-сриптах:
FIX(FY10, Jan:May)
 
    Acc2 = @XXPRIOR(Acc1); /* Macro */
    Acc3 = @PRIOR(Acc1);   /* Standart Function */

ENDFIX

Этот пример показывает результат работы скрипта:
Dec     Jan     Feb     Mar    Apr    May
                FY09    FY10    FY10    FY10   FY10   FY10
                ===     ===     ===     ===    ===    ===                       
Acc1            1100    1200    1000    1300   1300   1400
Acc2            #MI     1100    1200    1000   1300   1300
Acc3            #MI     #MI     1200    1000   1300   1300

Для детального изучения смотрите Technical Reference: Custom-Defined Macros

19 июл. 2010 г.

Оптимизация скриптов Essbase

Алгоритм оптимизации прост:
  • Запускаем расчет
  • Анализируем лог
  • Находим узкое место
  • Оптимизируем :)

1. Запускаем расчет.

Самый удобный лог для анализа - это лог esscmd. С его помощью и будем запускать скрипты. Не забудьте в скипте установить параметр "SET MSG SUMMARY" т.к. без него ничего интересного в логе вы не найдете.

Создаем calc-скрипт PL_Calc.csc, который необходимо анализировать:
SET MSG SUMMARY;
...
A = A + B;
...

Создаем esscmd-скрипт PL_Calc.scr:
output 1 "PL_Calc.log";
login "ess_server" "admin" "password";

updatevariable "vEntity" "ess_server" "PL" "" "EN_Russia";
updatevariable "vYear" "ess_server" "PL" "" "FY10";

select "PL" "PL";

runcalc 2 "PL_Calc";

OUTPUT 3;
exit;

Запускаем esscmd-скрипт и получаем PL_Calc.log:
esscmd PL_Calc.scr

2. Анализируем лог.

Для анализа мне понравился RightLog. Качаем и запускаем вот с такими параметрами:
RightLog.exe -i PL_Calc.log -s ; -t -d EUR -f "1012668|1012555|1012553|1012579|1003052" > PL_Calc.csv
Получили PL_Calc.csv

3. Находим узкое место.

Открываем PL_Calc.csv в Excel делаем расчетную колонку "Время исполнения" - вот и весь поиск.

4. Типовые проблемы производительности и возможные варианты решения.
Долго работает XREF - меняйте на партиции.
Долго считается формула на sparse элементе - используйте FRMLBOTTOMUP ON;
Долго работает агрегация - необходимо настраивать порядок измерений, кэши, использовать параллельные вычисления.

По настройке оптимизации предлагаю почитать "Optimizing Calc Scripts" by Edward Roske

P.S. Если необходимо просматривать информацию о кол-ве обработаных блоков
RightLog.exe -i PL_Calc.log -s ; -t -d EUR -f "1012668|1012555|1012553|1012579|1003052|Calculations:|Block Created|1012574|1017018" > PL_Calc.csv

18 июл. 2010 г.

PREVSIBLING vs CURRMBRRANGE

Хочу поделиться наблюдением.

Передо мной стояла задача создать динамическую статью Acc01_PrevYear, которая равняется статье Acc01 за прошлый год.

Вот такая формула работает 1 сек:
Acc01_PrevYear = Acc01->@PREVSIBLING(@CURRMBR("Years"))

Вот такая формула работает 0.01 сек:
Acc01_PrevYear = Acc01->@CURRMBRRANGE("Years", Lev, 0, -1, -1)

4 июл. 2010 г.

Essbase Integration Services VS Studio

В версии 11.1.1.0 появился новый продукт Essbase Studio, который пришел на замену Essbase Integration Services (EIS)

Чего пока что не может Studio 11.1.1.3:
- нельзя добавить колонку в таблицу источник, если эта таблица уже добавлена в Studio
- проблемы с загрузкой данных, если измерение создано вручную
- проблемы с cозданием drill-through отчетов для ненулевого уровня

Что понравилось:
+ удобный интерфейс
+ удобное управление подключениями
+ добавлены новые источники данных (EPM, Oracle BI)

В версии Studio 11.1.2 кое-что поправили, но с drill-through сложность так и осталась.

Выводы: до промышленной экплуатации Studio еще далеко, но знакомится с продуктом надо обязательно т.к. возможно скоро Studio заменит и EAS Console

P.S. Вот неплохой tutorial по Studio

28 июн. 2010 г.

Использование CDF (часть II)

Как передать в CDF значение переменной бизнес-правила?

К сожелению Java-класс, описаный в первой части, имеет ряд ограничений:
  • Невозможно передать значение переменной бизнес-правила
  • Нельзя использовать внутри FIX, получать код возврата

Что нужно сделать, чтобы CDF работала:
  • Настроить Essbase (см. часть I)
  • Создать и скомпилировать Java-класс
  • Настроить безопасность
  • Зарегистрировать Java-функцию в Essbase

1. Настраиваем Essbase.

см. часть I

2. Создаем и компилируем Java-класс.

2.1. Создаем файл ARBORPATH/java/udf/RunCmd.java
import java.util.*;
import java.io.*;

public class EssbaseRuRunTime {
public static void main(com.hyperion.essbase.calculator.Context ctx, String[] args)
{
int i,  n = args.length;
String Str = args[0];

for (i=1; i
Str = Str + " " + args[i];
}

try {Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(Str);
int exitVal = proc.waitFor();
System.out.println(args[0]+" ExitValue: " + exitVal);
}
catch(Exception e)
{
System.out.println(e.getMessage());
System.out.println(args[0]);
}

}
}
2.2 Компилируем класс из каталога, где он расположен
javac RunCmd.java
jar cf RunCmd.jar RunCmd.class
Примечание: компилировать версией Java, которая инсталирована с Essbase

3. Настраиваем безопасность

3.1. В файл ARBORPATH/java/udf.policy добавляем следующие строки:
grant codeBase "file:${java.home}/udf/RunCmd.jar" {
        permission java.security.AllPermission;
};

4. Регистрируем Java-функцию в Essbase

4.1. Выполняем слудующий MaxL скрипт
create function '@jRunCmd'
as 'RunCmd.jRun'
spec '@jRunCmd(arg1, arg2); @jRunCmd(arg1, @List(arg2, arg3,...));'
comment 'Execute shell command';

4.2. Перегружаем Essbase

Пример запуска CDF из бизнес-правила
Текст правила
VAR vA;
FIX(Act, BegBalance…..)
"FY10"
          (
           vA = @jRunCmd(
                          "../java/udf/scripts/alter_sub_var.sh"
                        , @LIST ("Cons_Scenario", @Name({vScenario}))
                        );      
           );
ENDFIX

Текст ALTER_SUB_VAR.SH:
./startMaxl.sh ../java/udf/scripts/alter_sub_var.mxl $1 $2

Текст ALTER_SUB_VAR.MXL:
login LOGINNAME identified by PASSWORD on SERVER;

alter system set variable $1 $2;

exit;


Полезные ресурсы
Документация Developing defined calculation functions
Блог hack4essbase.wordpress.com
Блог essbaselabs.blogspot.com

13 июн. 2010 г.

Использование CDF (часть I)

Что такое CDF?

CDF (custom defined functions) - это java-программы, которые можно использовать в скриптах расчетов (calc script) Essbase и бизнес-правилах Planning.

Что действительно необходимо на каждом проекте, так это запускать MaxL-скрипты или пакетные файлы (bat, cmd, sh) из бизнес-правил. Например запустить обновление replicated partition, загрузить данные и т.д.

Что нужно сделать, чтобы CDF работала:
1. Настроить Essbase
2. Создать и скомпилировать Java-класс
3. Настроить безопасность

Настраиваем Essbase.

1.1. Создаем папку ARBORPATH/java/udf
1.2. Изменяем настройку безопастности Java CDF
Необходимо в файле ARBORPATH/java/udf.policy снять комментарий с последней строки:
// **************************************************** 

// Permissions for all other classes.
// By default UDF sandbox is almost the same as applet environment, 
// with some additional restrictions.
grant {
            ……..
 permission java.util.PropertyPermission "java.vm.version", "read";
 permission java.util.PropertyPermission "java.vm.vendor", "read";
 permission java.util.PropertyPermission "java.vm.name", "read";

 // Uncomment the following line if you want to remove all restrictions
 permission java.security.AllPermission;
};


Создаем и компилируем Java-класс.

2.1. Создаем файл ARBORPATH/java/udf/EssbaseRuRunTime.java
import java.util.*;
import java.io.*;

public class EssbaseRuRunTime {
public static void main(com.hyperion.essbase.calculator.Context ctx, String[] args)
{
int i,  n = args.length;
String Str = args[0];

for (i=1; i
Str = Str + " " + args[i];
}

try {Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(Str);
int exitVal = proc.waitFor();
System.out.println(args[0]+" ExitValue: " + exitVal);
}
catch(Exception e)
{
System.out.println(e.getMessage());
System.out.println(args[0]);
}

}
}
2.2 Компилируем класс из каталога, где он расположен
javac –classpath ../essbase.jar EssbaseRuRunTime.java
jar cf EssbaseRuRunTime.jar EssbaseRuRunTime.class
Примечание: компилировать версией Java, которая инсталирована с Essbase

Настраиваем безопасность

3.1. В файл ARBORPATH/java/udf.policy добавляем следующие строки:
grant codeBase "file:${java.home}/udf/EssbaseRuRunTime.jar" {
        permission java.security.AllPermission;
};
3.2. Перегружаем Essbase

Пример запуска CDF из calc-script
FIX
   ... что-то считаем
ENDFIX

RUNJAVA EssbaseRuRunTime "../java/udf/scripts/alter_sub_var.sh" "BudYear" &Act_Year;

FIX
   ... что-то считаем
ENDFIX
Примечание: внутри FIX нельзя запускать EssbaseRuRunTime

Полезные ресурсы
Документация Developing defined calculation functions
Блог hack4essbase.wordpress.com
Блог essbaselabs.blogspot.com