Текущее время: Пт, мар 29 2024, 02:28

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 9 ] 
Автор Сообщение
 Заголовок сообщения: Агрегат по "неагрегируемому" показателю
СообщениеДобавлено: Ср, дек 14 2016, 13:35 
Младший специалист
Младший специалист

Зарегистрирован:
Пн, июн 25 2007, 22:27
Сообщения: 95
Пол: Мужской
Коллеги, вопрос возник. Про бивишные агрегаты, типа агрегации и вообще.
Вот есть некие данные, для примера - чеки. Есть показатели типа количества и суммы, с которыми все просто.
И есть показатели типа "количество чеков" или "количество уникальных покупателей" и т.д. Их особенность в том, что их нельзя суммировать, их надо считать по принципу "distinct count" в зависимости от текущих разверток. Это связано с тем, что по группе товаров 1 может быть 5 чеков, по группе 2 - 10 чеков, а по родительской группе - не 15, а 12 (т.к. в трех чеках присутствуют товары из обеих дочерних групп). Ситуация усложняется тем, что у товара может быть пара десятков разных атрибутов и пользователь может захотеть посчитать кол-во чеков в любом сочетании этих атрибутов.

Самый простой вариант - сделать в бексе расчетный показатель и в нем в свойствах агрегации включить "подсчет отдельных значений". Это работает, но на больших объемах - крайне медленно.
Можно сделать переменную-формулу "путь замены" с типом "Константа 1" для измерения "ID чека". Это по сути то же самое и работает с той же скоростью.
Можно для показателя на уровне RSA1 настроить спецагрегацию, но тогда для включения его в агрегат нужно в этот агрегат добавить признак, на котором эта спецагрегация настроена (в случае чеков - ID чека). Что автоматически превращает этот агрегат во второй такой же кубик.

Мне тут показали нечто похожее в MSAS - так вот там каким-то образом рассчитывается что-то типа агрегата по такому показателю. Т.е. ставится тип расчета "distinct count", выбирается произвольный набор измерений и вперед. Сравнили производительность на одних и тех же данных - даже на средних объемах получается, что MSAS уделывает BW в десятки раз. Абыдно, блин. Никогда не сталкивался с MSAS изнутри и не знаю, как он это делает, но результат меня впечатлил.

Собственно, хотел спросить: а кто как решает в BW подобные задачки? Может есть какой-то другой способ, кроме тех, которые я перечислил?
Естественно, имеется ввиду BW не на хане.


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Агрегат по "неагрегируемому" показателю
СообщениеДобавлено: Ср, дек 14 2016, 15:53 
Гуру-эксперт
Гуру-эксперт
Аватара пользователя

Зарегистрирован:
Вс, янв 11 2009, 14:41
Сообщения: 902
Откуда: Москва
Пол: Мужской
evm написал:
Мне тут показали нечто похожее в MSAS - так вот там каким-то образом рассчитывается что-то типа агрегата по такому показателю. Т.е. ставится тип расчета "distinct count", выбирается произвольный набор измерений и вперед. Сравнили производительность на одних и тех же данных - даже на средних объемах получается, что MSAS уделывает BW в десятки раз. Абыдно, блин. Никогда не сталкивался с MSAS изнутри и не знаю, как он это делает, но результат меня впечатлил.
Что-то типа агрегата?! Очень похоже на материализованное представление (Oracle). Но в BW проблема не на стороне БД (или агрегатов). OLAP-овская часть, написанная на ABAP-е, очень сильно тормозит. Запустите ваш отчет в SE30 и посмотрите на процентное отношение работы БД и ABAP-а. Проблема производительности спецагрегации исключительно в стандартном ABAP-е.

PS: Шарик с гелием в квартире может подняться максимум до потолка


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Агрегат по "неагрегируемому" показателю
СообщениеДобавлено: Чт, дек 15 2016, 11:31 
Младший специалист
Младший специалист

Зарегистрирован:
Пн, июн 25 2007, 22:27
Сообщения: 95
Пол: Мужской
Да в данном случае не так уж и важно, в каком именно месте затык. Вопрос в том, что на массе проектов BW внедряется именно как замена MSAS, и достаточно сложно отвечать на вопросы заказчика, почему замена дешевого MSAS на дорогой BW приводит в ряде случаев к падению скорости во много раз, на сопоставимом железе. Продолжая аналогию с шариком - меняешь дешевую квартиру на дорогую, а потолок в ней внезапно становится существенно ниже. Пусть даже и не во всех комнатах, а в некоторых.

Собственно, основной вопрос остается в силе: если есть какие-то способы решения в BW подобной задачки, отличные от тех, которые я перечислил - был бы рад послушать.


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Агрегат по "неагрегируемому" показателю
СообщениеДобавлено: Пт, дек 16 2016, 10:48 
Гуру-эксперт
Гуру-эксперт
Аватара пользователя

Зарегистрирован:
Вс, янв 11 2009, 14:41
Сообщения: 902
Откуда: Москва
Пол: Мужской
Цитата:
Да в данном случае не так уж и важно, в каком именно месте затык. Вопрос в том, что на массе проектов BW внедряется именно как замена MSAS, и достаточно сложно отвечать на вопросы заказчика, почему замена дешевого MSAS на дорогой BW приводит в ряде случаев к падению скорости во много раз, на сопоставимом железе. Продолжая аналогию с шариком - меняешь дешевую квартиру на дорогую, а потолок в ней внезапно становится существенно ниже. Пусть даже и не во всех комнатах, а в некоторых.
Тут остается толькоИзображение
Цитата:
Собственно, основной вопрос остается в силе: если есть какие-то способы решения в BW подобной задачки, отличные от тех, которые я перечислил - был бы рад послушать.
Можно попробовать еще такой вариант. Берем простой случай. Куб CUBE, состоящий из двух признаков и показателя: GR1, GR2, KF. Предположим, что куб сжат. Предположим, что у нас есть DSO следующей структуры: GR1, GR2, CHECK, где все три поля входят в состав первичного ключа. Создаем BEX-запрос на кубе, следующей развертки: GR1, GR2, KF. Создаем BADI для виртуальных признаков/показателей. Логика в BADI будет следующей: определяем состав признаков в развертке и для каждой обрабатываемой записи выполняем запрос с динамическим WHERE-условием, рассчитывая показатель KF:
Code:
SELECT
  COUNT( DISTINCT CHECK )
FROM
  DSO
WHERE
  (var_where)

где var_where:
  GR1 = :GR1 AND
  GR2 = :GR2

Если убрать из развертки запроса признак GR2, тогда запрос трансформируется в
Code:
SELECT
  COUNT( DISTINCT CHECK )
FROM
  DSO
WHERE
  GR1 = :GR1

Такой вариант может быть быстрее, чем спецагрегация, потому что в развертку неявно не добавляется признак CHECK, данных возвращается меньше (особенно, если CHECK-ов много, а сочетаний групп относительно мало) и OLAP-овский ABAP не нагружается чрезмерно. То есть нагрузка с сервера приложений переносится на уровень БД. Опять-таки в SE30 можно будет наблюдать за изменением процентного соотношения БД/ABAP и сделать правильные выводы.

Ограничения на решение: Если убрать GR1 из развертки, а оставить GR2, тогда на DSO надо создавать допиндекс. Чем больше будет признаков GRn, тем бессмысленнее будет становиться решение. Но для статических запросов и с небольшим кол-вом N (наприме, до 3-х) - может сгодиться.


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Агрегат по "неагрегируемому" показателю
СообщениеДобавлено: Пт, дек 16 2016, 11:52 
Младший специалист
Младший специалист

Зарегистрирован:
Пн, июн 25 2007, 22:27
Сообщения: 95
Пол: Мужской
murmur написал:
Логика в BADI будет следующей: определяем состав признаков в развертке

А можно вот в этом месте поподробнее? Ссылку где почитать или пример.
Просто когда я делал виртуальные признаки/показатели через BADI, у меня сложилось впечатление, что в BADI приходят детальные данные в полной структуре куба, и что вся эта виртуальная история выполняется до агрегации данных. Способа изнутри BADI узнать текущую структуру развертки я не знаю.

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


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Агрегат по "неагрегируемому" показателю
СообщениеДобавлено: Пт, дек 16 2016, 12:13 
Гуру-эксперт
Гуру-эксперт
Аватара пользователя

Зарегистрирован:
Вс, янв 11 2009, 14:41
Сообщения: 902
Откуда: Москва
Пол: Мужской
Данные действительно приходят до агрегации, но для повторяющихся сочетаний GR1, GR2 SELECT-запрос потребуется выполнять только один раз и результат сохраняем в хэш-таблицу. Для первого сочетания KF = 1, для остальных - KF = 0. Признаки, входящие в развертку, узнать можно. Если будет свободное время, попробую сделать и выложу пример.

PS: Кроме того, всегда есть возможность создать виртуальный куб на основе ФМ (там уже можно будет работать с агрегированными данными). Задача решаема, но требуется время и желание во всем этом ковыряться.


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Агрегат по "неагрегируемому" показателю
СообщениеДобавлено: Ср, дек 21 2016, 10:41 
Гуру-эксперт
Гуру-эксперт
Аватара пользователя

Зарегистрирован:
Вс, янв 11 2009, 14:41
Сообщения: 902
Откуда: Москва
Пол: Мужской
Попытался сделать (см. ниже). Но до конца не докрутил. Делал в мини-SAP (версия SAPKW70211), не смог отключить OLAP local cache, чтобы для каждого шага навигации отрабатывал BADI-код - см. ноту 2017248 Disabling internal OLAP cache buffers (local cache). Если в отчете выводить подитоги, то рассчитаны они будут неверно (у OLAP-а не осталось основы для расчета, мы ее отняли). Определение признаков в развертке сделано с помощью дополнительных переменных *_EXT (см. в коде).

То есть для статического отчета без подитогов можно использовать, но в целом решение хреновое ;)

Code:
DSO (/BIC/ADSO00) - объединение чеков в группы
/BIC/GR1 /BIC/GR2 /BIC/CHECK
01       01       00001
01       01       00002
01       01       00003
01       01       00004
01       01       00005
01       02       00004
01       02       00005
01       02       00006
01       02       00007
01       02       00008
01       02       00009
01       02       00010
02       01       00006
02       01       00007
02       01       00008

Code:
DSO_CHK (/BIC/ADSO_CHK00) - чеки
/BIC/CHECK /BIC/KEYFG
00001                      10,000
00002                      20,000
00003                      30,000
00004                      40,000
00005                      50,000
00006                      60,000
00007                      70,000
00008                      80,000
00009                      90,000
00010                     100,000

Code:
CUBE состоит из GR1, GR2, и пустого KEYFG: в него прогружены данные из DSO

Code:
TYPES:
    BEGIN OF THash,
      gr1 TYPE /bic/oigr1,
      gr2 TYPE /bic/oigr2,
      cnt TYPE i,
    END OF THash.

  DATA:
    g_ht_hash TYPE HASHED TABLE OF THash
    WITH UNIQUE KEY gr1 gr2.

  data P_CHA_GR1 type I .
  data P_CHA_GR2 type I .
  data P_KYF_KEYFG type I .
  data P_CHA_GR1_EXT type I .
  data P_CHA_GR2_EXT type I .

method IF_EX_RSR_OLAP_BADI~DEFINE.

  DATA:
    l_s_chanm   TYPE rrke_s_chanm,
    l_kyfnm     TYPE rsd_kyfnm.

  CASE i_s_rkb1d-infocube.

    WHEN 'CUBE'.

      l_s_chanm-chanm = 'GR1'.
      l_s_chanm-mode  = rrke_c_mode-read.
      APPEND l_s_chanm TO c_t_chanm.

      l_s_chanm-chanm = 'GR2'.
      l_s_chanm-mode  = rrke_c_mode-read.
      APPEND l_s_chanm TO c_t_chanm.

      l_kyfnm = 'KEYFG'.
      APPEND l_kyfnm TO c_t_kyfnm.

  ENDCASE.
endmethod.

method IF_EX_RSR_OLAP_BADI~INITIALIZE.

* расширено
  REFRESH:
    g_ht_hash[].

  DATA: l_global_name TYPE string.
  FIELD-SYMBOLS:
        <l_global>    TYPE i,
        <l_s_sfc>     TYPE rrkg_s_sfc,
        <l_s_sfk>     TYPE rrkg_s_sfk.

* there's no need to change this method
* Just create attributes for each charactersitic
* with name P_CHA_<characteristic> TYPE i.
* and constants for each key figure with name
* P_KYF_<key figure> TYPE i.

  CLASS cl_exm_im_rsr_olap_badi DEFINITION LOAD.

* get field postions for characteristics in structure
  LOOP AT i_th_sfc ASSIGNING <l_s_sfc>
       WHERE user_exit NE rrke_c_mode-none.

* field name in structure is keyreturnnm
* name of the global variable
    CONCATENATE 'P_CHA' <l_s_sfc>-chanm
        INTO l_global_name
        SEPARATED BY '_'.
* fill the global variable
    UNASSIGN <l_global>.
    ASSIGN (l_global_name) TO <l_global>.
    CHECK <l_global> IS ASSIGNED.
    <l_global> = cl_exm_im_rsr_olap_badi=>get_field_position_d(
                                       i_fieldnm = <l_s_sfc>-keyreturnnm
                                       i_s_data  = i_s_data ).

*   расширено
    CONCATENATE 'P_CHA' <l_s_sfc>-chanm 'EXT'
      INTO l_global_name
      SEPARATED BY '_'.

    UNASSIGN <l_global>.
    ASSIGN (l_global_name) TO <l_global>.
    CHECK <l_global> IS ASSIGNED.
    <l_global> = cl_exm_im_rsr_olap_badi=>get_field_position_d(
                                       i_fieldnm = <l_s_sfc>-sidreturnnm
                                       i_s_data  = i_s_data ).
  ENDLOOP.

* get field positions for key figures in structure
  LOOP AT i_th_sfk ASSIGNING <l_s_sfk>
       WHERE value_returnnm IS NOT INITIAL.
* name of the global variable
    CONCATENATE 'P_KYF' <l_s_sfk>-kyfnm
        INTO l_global_name
        SEPARATED BY '_'.
* fill the global variable
    UNASSIGN <l_global>.
    ASSIGN (l_global_name) TO <l_global>.
    CHECK <l_global> IS ASSIGNED.
    <l_global> = cl_exm_im_rsr_olap_badi=>get_field_position_d(
                                       i_fieldnm = <l_s_sfk>-value_returnnm
                                       i_s_data  = i_s_data ).
  ENDLOOP.

endmethod.

method IF_EX_RSR_OLAP_BADI~COMPUTE.

  FIELD-SYMBOLS:
    <gr1> TYPE /bic/oigr1,
    <gr2> TYPE /bic/oigr2,
    <gr1_ext> TYPE i,
    <gr2_ext> TYPE i,
    <keyfg> TYPE /bic/oikeyfg.

  ASSIGN COMPONENT P_CHA_GR1 OF STRUCTURE c_s_data TO <gr1>.
  ASSIGN COMPONENT P_CHA_GR2 OF STRUCTURE c_s_data TO <gr2>.
  ASSIGN COMPONENT P_CHA_GR1_EXT OF STRUCTURE c_s_data TO <gr1_ext>.
  ASSIGN COMPONENT P_CHA_GR2_EXT OF STRUCTURE c_s_data TO <gr2_ext>.
  ASSIGN COMPONENT P_KYF_KEYFG OF STRUCTURE c_s_data TO <keyfg>.

  IF <keyfg> IS ASSIGNED.

    DATA:
      lt_where TYPE TABLE OF string,
      ls_hash LIKE LINE OF g_ht_hash[].

    IF <gr1_ext> <> 0.
      APPEND 't1~/bic/gr1 = <gr1>' TO lt_where.
      ls_hash-gr1 = <gr1>.
    ENDIF.

    IF <gr2_ext> <> 0.
      APPEND 't1~/bic/gr2 = <gr2>' TO lt_where.
      ls_hash-gr2 = <gr2>.
    ENDIF.

    DATA:
      l_where TYPE string.

    CONCATENATE LINES OF lt_where INTO l_where SEPARATED BY ' AND '.

    DATA:
      l_count TYPE i.

    SELECT
      COUNT( DISTINCT t1~/bic/check )
    INTO
      l_count
    FROM
      /bic/adso00 AS t1 INNER JOIN /bic/adso_chk00 AS t2 ON
      t1~/bic/check = t2~/bic/check
    WHERE
      (l_where).

    FIELD-SYMBOLS:
      <hash> LIKE ls_hash.

    READ TABLE g_ht_hash
    WITH TABLE KEY
      gr1 = ls_hash-gr1
      gr2 = ls_hash-gr2
    ASSIGNING
      <hash>.

    IF sy-subrc = 0.
      CLEAR <keyfg>.
    ELSE.
      <keyfg> = l_count.

      ls_hash-cnt = l_count.
      INSERT ls_hash INTO TABLE g_ht_hash.
    ENDIF.
  ENDIF.

endmethod.


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
 Заголовок сообщения: Re: Агрегат по "неагрегируемому" показателю
СообщениеДобавлено: Ср, дек 21 2016, 11:21 
Младший специалист
Младший специалист

Зарегистрирован:
Пн, июн 25 2007, 22:27
Сообщения: 95
Пол: Мужской
Спасибо. Не стоило так уж утруждаться, мне просто стало интересно про определение развертки изнутри бади для вирт. признаков. В остальном идея была понятна. Может при случае попробую, хотя решение и правда монстроидальное.


Принять этот ответ
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Агрегат по "неагрегируемому" показателю
СообщениеДобавлено: Ср, дек 21 2016, 11:47 
Гуру-эксперт
Гуру-эксперт
Аватара пользователя

Зарегистрирован:
Вс, янв 11 2009, 14:41
Сообщения: 902
Откуда: Москва
Пол: Мужской
evm написал:
Не стоило так уж утруждаться, мне просто стало интересно
Мне тоже 8)


Принять этот ответ
Вернуться к началу
 Профиль Отправить email  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 9 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: Ahrefs [Bot]


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB