Оптимизация ABAP-а

Автор Uukrul, Травень 16, 2008, 11:39:58 ДП

Попередня тема - Наступна тема

0 Користувачі і 2 Гостей дивляться цю тему.

Dmitriy

Цитата: Uukrul від Червень 05, 2009, 05:23:09 ПП
Синтаксис не подскажешь сразу, а то я что-то найти не могу..
Нет, к сожелению, этот код не "засолил", повезло в свое время по поводу мегаотчетов, но может мужики-абаперы подскажут что, залез в исходники - много их... Нормально просто всегда индексы работали, а еще и с базисом общался, грамотный базисник дюжины начинающих абаперов стоит, если не вредный. ;) А потом уже (по поводу больших отчетов), мы просто присаживались с консулами (когда они были!) и предметно общаясь, договаривались, что они, как постановщики, будут клиенту говорить, можно/нельзя, а то иногда такие казусы... ::) Пошукаю, если найду - отпишу.
 

Паганель

Цитата: Dmitriy від Червень 05, 2009, 10:18:09 ПП
А потом уже (по поводу больших отчетов), мы просто присаживались с консулами (когда они были!) и предметно общаясь, договаривались, что они, как постановщики, будут клиенту говорить, можно/нельзя, а то иногда такие казусы... ::) Пошукаю, если найду - отпишу.
Хорошо, наверное тебе, Дима, просто, нет у меня консулов, «Аз есмь...», и косул, и абапер, в одном лице :-), и задачу ставят не в виде ТЗ, а ближе к ФД (функциональному требованию, общему описанию, как должно быть) ... ну как говорят "и кузнец, и жнец, и трубе дудец"....

Dmitriy

Цитата: Паганель від Червень 05, 2009, 10:24:52 ПП
Хорошо, наверное тебе, Дима, просто, нет у меня консулов, «Аз есмь...», и косул, и абапер, в одном лице :-), и задачу ставят не в виде ТЗ, а ближе к ФД (функциональному требованию, общему описанию, как должно быть) ... ну как говорят "и кузнец, и жнец, и трубе дудец"....
Да это понятно, просто когда опыта поднаберешь, сможешь авторитетом "давить". А то мечтателей много, дай им то, это, а SAP ведь тоже не резиновый. :D

Паганель

Цитата: Dmitriy від Червень 05, 2009, 10:29:12 ПП
Да это понятно, просто когда опыта поднаберешь, сможешь авторитетом "давить". А то мечтателей много, дай им то, это, а SAP ведь тоже не резиновый. :D
Знаем"с мы таких "мечтателей", сами такие, как сделаем, потом еще недельку оптимизируем .....

Дима, а ты о чем?

Dmitriy

#79
Цитата: Паганель від Червень 05, 2009, 10:31:33 ПП
Знаем"с мы таких "мечтателей", сами такие, как сделаем, потом еще недельку оптимизируем .....

Дима, а ты о чем?
О понимании бизнес-процессов компании самим, руководством оной и умением объяснить Клиенту, не то, что он не прав, а то, как надо, т.е. научить/объяснить и подвести к тому, чтобы он был прав, но с учетом специфики параметров "железа" на котором все это дело функционирует и системных настроек.

NachDenken

не могу найти пост где месье Паганель рассказывал про зависимость условий where и выбор индекса
действительно ли это так

Паганель

Цитата: NachDenken від Червень 10, 2009, 11:26:06 ДП
не могу найти пост где месье Паганель рассказывал про зависимость условий where и выбор индекса
действительно ли это так
страницей выше в этой же теме (только это вопрос спорный)
http://sapforum.biz/index.php/topic,174.msg4061.html#msg4061

NachDenken

еще нужен синтаксис хинта ?
%_HINTS ORACLE 'index(MKPF "MKPF~Zblabla")'.

NachDenken

по поводу индекса,
думаю со стратегией выбора индекса в sap не все так просто,
1 и тот же селект и условия, при одинаковых индексах в разных мандантах выбор разный.

Uukrul

Цитата: NachDenken від Червень 11, 2009, 01:26:03 ПП
1 и тот же селект и условия, при одинаковых индексах в разных мандантах выбор разный.
Ну там еще статистика индекса смотрится... т.е. для теста желательно сбор статистики сделать в обоих системах, посмотреть на результат, ну если данные в системах одинаковые, то должно совпасть и уже потом запускать отчеты и смотреть на индексы.

Паганель

#85
Тут вот опять делаю оптимизацию, странные результаты:  

LOOP AT gt_alvtab INTO ls_alvtab - 33 302 061
LOOP AT gt_alvtab ASSIGNING <fs_alvtab>. - 36 540 526


Странно....  :o

Может это для небольшого к-ва тестовых данных?

Паганель

Ошибся, в одном месте не заменил
PERFORM select_add_data CHANGING ls_alvtab на <fs_alvtab>.
Странно,  не думаю что из-за этого такой разброс?


Вопросик, каким образом, через <fs_alvtab> или еще как то можно оптимизировать такой код?

" Очищаем все пустые
LOOP AT gt_alvtab INTO ls_alvtab WHERE is_null = 1.
    DELETE gt_alvtab INDEX sy-tabix.
    "DELETE gt_alvtab FROM ls_alvtab. " INDEX sy-tabix.
ENDLOOP.

Удав

Замени выборку данных на свою и посмотри результаты разных методов ;)

REPORT  z_test_delete.

DATA: BEGIN OF gs_alvtab,
        belnr TYPE bkpf-belnr,
        is_null(1) TYPE c,
      END OF gs_alvtab,
      gt_alvtab LIKE STANDARD TABLE OF gs_alvtab,
      gt_alvtab2 LIKE STANDARD TABLE OF gs_alvtab,
      tabix TYPE sy-tabix,
      t1 TYPE i,
      t2 TYPE i.

FIELD-SYMBOLS: <fs_alvtab> LIKE gs_alvtab.

START-OF-SELECTION.

  SELECT belnr
  INTO CORRESPONDING FIELDS OF TABLE gt_alvtab
  FROM bkpf
  WHERE bukrs = '1100'.

  LOOP AT gt_alvtab ASSIGNING <fs_alvtab>.
    tabix = sy-tabix MOD 5.
    WRITE tabix TO <fs_alvtab>-is_null LEFT-JUSTIFIED.
  ENDLOOP.
  gt_alvtab2 = gt_alvtab.
  tabix = LINES( gt_alvtab ).
  WRITE: /(25) 'Count of records', tabix.
  GET RUN TIME FIELD t1.
  LOOP AT gt_alvtab ASSIGNING <fs_alvtab> WHERE is_null = 1.
    DELETE gt_alvtab INDEX sy-tabix.
  ENDLOOP.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  tabix = LINES( gt_alvtab ).
  WRITE: /(25) 'Loop w/o sort', t1, tabix.
  GET RUN TIME FIELD t1.
  SORT gt_alvtab2 BY is_null.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(25) 'Sort', t1.
  gt_alvtab = gt_alvtab2.
  GET RUN TIME FIELD t1.
  LOOP AT gt_alvtab ASSIGNING <fs_alvtab> WHERE is_null = 1.
    DELETE gt_alvtab INDEX sy-tabix.
  ENDLOOP.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  tabix = LINES( gt_alvtab ).
  WRITE: /(25) 'Loop with sort', t1, tabix.
  gt_alvtab = gt_alvtab2.
  GET RUN TIME FIELD t1.
  READ TABLE gt_alvtab WITH KEY is_null = 1
    BINARY SEARCH
    TRANSPORTING NO FIELDS.
  tabix = sy-tabix.

  WHILE sy-subrc = 0.
    sy-subrc = 0.
    READ TABLE gt_alvtab ASSIGNING <fs_alvtab> INDEX tabix.
    IF sy-subrc <> 0.
      EXIT.
    ENDIF.
    IF <fs_alvtab>-is_null <> 1.
      sy-subrc = 4.
    ELSE.
      DELETE gt_alvtab INDEX tabix.
*      ADD 1 TO tabix.
    ENDIF.
  ENDWHILE.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  tabix = LINES( gt_alvtab ).
  WRITE: /(25) 'Read .. binary search', t1, tabix.

  gt_alvtab = gt_alvtab2.
  GET RUN TIME FIELD t1.
  DELETE gt_alvtab WHERE is_null = 1.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  tabix = LINES( gt_alvtab ).
  WRITE: /(25) 'Delete', t1, tabix.

Паганель

#88
Цитата: Удав від Червень 17, 2009, 04:32:35 ПП
Замени выборку данных на свою и посмотри результаты разных методов ;)

REPORT  z_test_delete.

DATA: BEGIN OF gs_alvtab,
       belnr TYPE bkpf-belnr,
       is_null(1) TYPE c,
     END OF gs_alvtab,
     gt_alvtab LIKE STANDARD TABLE OF gs_alvtab,
     gt_alvtab2 LIKE STANDARD TABLE OF gs_alvtab,
     tabix TYPE sy-tabix,
     t1 TYPE i,
     t2 TYPE i.

FIELD-SYMBOLS: <fs_alvtab> LIKE gs_alvtab.

START-OF-SELECTION.

 SELECT belnr
 INTO CORRESPONDING FIELDS OF TABLE gt_alvtab
 FROM bkpf
 WHERE bukrs = '1100'.

 LOOP AT gt_alvtab ASSIGNING <fs_alvtab>.
   tabix = sy-tabix MOD 5.
   WRITE tabix TO <fs_alvtab>-is_null LEFT-JUSTIFIED.
 ENDLOOP.
 gt_alvtab2 = gt_alvtab.
 tabix = LINES( gt_alvtab ).
 WRITE: /(25) 'Count of records', tabix.
 GET RUN TIME FIELD t1.
 LOOP AT gt_alvtab ASSIGNING <fs_alvtab> WHERE is_null = 1.
   DELETE gt_alvtab INDEX sy-tabix.
 ENDLOOP.
 GET RUN TIME FIELD t2.
 t1 = t2 - t1.
 tabix = LINES( gt_alvtab ).
 WRITE: /(25) 'Loop w/o sort', t1, tabix.
 GET RUN TIME FIELD t1.
 SORT gt_alvtab2 BY is_null.
 GET RUN TIME FIELD t2.
 t1 = t2 - t1.
 WRITE: /(25) 'Sort', t1.
 gt_alvtab = gt_alvtab2.
 GET RUN TIME FIELD t1.
 LOOP AT gt_alvtab ASSIGNING <fs_alvtab> WHERE is_null = 1.
   DELETE gt_alvtab INDEX sy-tabix.
 ENDLOOP.
 GET RUN TIME FIELD t2.
 t1 = t2 - t1.
 tabix = LINES( gt_alvtab ).
 WRITE: /(25) 'Loop with sort', t1, tabix.
 gt_alvtab = gt_alvtab2.
 GET RUN TIME FIELD t1.
 READ TABLE gt_alvtab WITH KEY is_null = 1
   BINARY SEARCH
   TRANSPORTING NO FIELDS.
 tabix = sy-tabix.

 WHILE sy-subrc = 0.
   sy-subrc = 0.
   READ TABLE gt_alvtab ASSIGNING <fs_alvtab> INDEX tabix.
   IF sy-subrc <> 0.
     EXIT.
   ENDIF.
   IF <fs_alvtab>-is_null <> 1.
     sy-subrc = 4.
   ELSE.
     DELETE gt_alvtab INDEX tabix.
*      ADD 1 TO tabix.
   ENDIF.
 ENDWHILE.
 GET RUN TIME FIELD t2.
 t1 = t2 - t1.
 tabix = LINES( gt_alvtab ).
 WRITE: /(25) 'Read .. binary search', t1, tabix.

 gt_alvtab = gt_alvtab2.
 GET RUN TIME FIELD t1.
 DELETE gt_alvtab WHERE is_null = 1.
 GET RUN TIME FIELD t2.
 t1 = t2 - t1.
 tabix = LINES( gt_alvtab ).
 WRITE: /(25) 'Delete', t1, tabix.


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

Тут есть подсказки не только как оптимизировать цикл с удалением, но и нашел для себя как оптимизировать еще один цикл ....

Мои результаты:
Рис1 и Рис2. странно что такой расброс в результатах для "Удаление. Loop w/o sort."
между двумя запусками ..


Как вижу быстрее всего работает DELETE gt_alvtab WHERE is_null = 1.

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


NachDenken


подскажите как средствами abap
сделать такой запрос только к внутренней itab

select p1 max(p2) sum(p3)
from blabla
group by p1

collect мне суммирует p2
Спасибо.

Паганель

#90
Цитата: NachDenken від Червень 18, 2009, 10:04:00 ДП
подскажите как средствами abap
сделать такой запрос только к внутренней itab

select p1 max(p2) sum(p3)
from blabla
group by p1

collect мне суммирует p2
Спасибо.

вроде бы только collect  или READ/LOOP c записью в еще одну табличку.

С  collect не работал, так как не очень понял как он работает и как выбирает поля по которым суммировать, но тут есть люди которые его наверняка юзали.

Выше в этой теме Уукрул приводил пример суммирования http://sapforum.biz/index.php/topic,174.msg726.html#msg726


Паганель

2Удав
Цитата: Удав від Червень 17, 2009, 04:32:35 ПП
Замени выборку данных на свою и посмотри результаты разных методов ;)

REPORT  z_test_delete.

DATA: BEGIN OF gs_alvtab,
        belnr TYPE bkpf-belnr,
        is_null(1) TYPE c,
      END OF gs_alvtab,
      gt_alvtab LIKE STANDARD TABLE OF gs_alvtab,
      gt_alvtab2 LIKE STANDARD TABLE OF gs_alvtab,
      tabix TYPE sy-tabix,
      t1 TYPE i,
      t2 TYPE i.

FIELD-SYMBOLS: <fs_alvtab> LIKE gs_alvtab.

START-OF-SELECTION.

  SELECT belnr
  INTO CORRESPONDING FIELDS OF TABLE gt_alvtab
  FROM bkpf
  WHERE bukrs = '1100'.

  LOOP AT gt_alvtab ASSIGNING <fs_alvtab>.
    tabix = sy-tabix MOD 5.
    WRITE tabix TO <fs_alvtab>-is_null LEFT-JUSTIFIED.
  ENDLOOP.
  gt_alvtab2 = gt_alvtab.
  tabix = LINES( gt_alvtab ).
  WRITE: /(25) 'Count of records', tabix.
  GET RUN TIME FIELD t1.
  LOOP AT gt_alvtab ASSIGNING <fs_alvtab> WHERE is_null = 1.
    DELETE gt_alvtab INDEX sy-tabix.
  ENDLOOP.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  tabix = LINES( gt_alvtab ).
  WRITE: /(25) 'Loop w/o sort', t1, tabix.
  GET RUN TIME FIELD t1.
  SORT gt_alvtab2 BY is_null.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  WRITE: /(25) 'Sort', t1.
  gt_alvtab = gt_alvtab2.
  GET RUN TIME FIELD t1.
  LOOP AT gt_alvtab ASSIGNING <fs_alvtab> WHERE is_null = 1.
    DELETE gt_alvtab INDEX sy-tabix.
  ENDLOOP.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  tabix = LINES( gt_alvtab ).
  WRITE: /(25) 'Loop with sort', t1, tabix.
  gt_alvtab = gt_alvtab2.
  GET RUN TIME FIELD t1.
  READ TABLE gt_alvtab WITH KEY is_null = 1
    BINARY SEARCH
    TRANSPORTING NO FIELDS.
  tabix = sy-tabix.

  WHILE sy-subrc = 0.
    sy-subrc = 0.
    READ TABLE gt_alvtab ASSIGNING <fs_alvtab> INDEX tabix.
    IF sy-subrc <> 0.
      EXIT.
    ENDIF.
    IF <fs_alvtab>-is_null <> 1.
      sy-subrc = 4.
    ELSE.
      DELETE gt_alvtab INDEX tabix.
*      ADD 1 TO tabix.
    ENDIF.
  ENDWHILE.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  tabix = LINES( gt_alvtab ).
  WRITE: /(25) 'Read .. binary search', t1, tabix.

  gt_alvtab = gt_alvtab2.
  GET RUN TIME FIELD t1.
  DELETE gt_alvtab WHERE is_null = 1.
  GET RUN TIME FIELD t2.
  t1 = t2 - t1.
  tabix = LINES( gt_alvtab ).
  WRITE: /(25) 'Delete', t1, tabix.


Можеш обьяснить этот кусок кода:

READ TABLE gt_alvtab WITH KEY is_null = 1
BINARY SEARCH
TRANSPORTING NO FIELDS.
tabix = sy-tabix.

WHILE sy-subrc = 0.
  sy-subrc = 0.
  READ TABLE gt_alvtab ASSIGNING <fs_alvtab> INDEX tabix.
  IF sy-subrc <> 0.
    EXIT.
  ENDIF.
  IF <fs_alvtab>-is_null <> 1.
    sy-subrc = 4.
  ELSE.
    DELETE gt_alvtab INDEX tabix.
*      ADD 1 TO tabix.
  ENDIF.
ENDWHILE.

Uukrul

Цитата: NachDenken від Червень 18, 2009, 10:04:00 ДП
collect мне суммирует p2
Ну таки да... руками через LOOP AT ENDLOOP. разве что... я что-то никаких описаний типа отключения суммирования для цифровых полей не нашел  ::)

NachDenken

помните ?
1) call function селект ...new task и потом их ловить в процедурке on end task
2) запустить  job_open submit селект

1 пункт не фоновый получается, а просто параллельный
2) и фоновый и паралельный

Удав

Цитата: Паганель від Червень 18, 2009, 10:52:09 ДП
2Удав
Можеш обьяснить этот кусок кода:

READ TABLE gt_alvtab WITH KEY is_null = 1
BINARY SEARCH
TRANSPORTING NO FIELDS.
tabix = sy-tabix.

WHILE sy-subrc = 0.
  sy-subrc = 0.
  READ TABLE gt_alvtab ASSIGNING <fs_alvtab> INDEX tabix.
  IF sy-subrc <> 0.
    EXIT.
  ENDIF.
  IF <fs_alvtab>-is_null <> 1.
    sy-subrc = 4.
  ELSE.
    DELETE gt_alvtab INDEX tabix.
*      ADD 1 TO tabix.
  ENDIF.
ENDWHILE.

Конечно :)
1.Сначала таблица сортируется по is_null по возрастанию (выше по коду)
2.Ищется 1-я запись с is_null = 1 по binary search
3.Удаляются записи, у которых is_null = 1.
Как только попадется запись, у которой is_null > 1 или достигнут конец таблицы - выход из цикла.

Martha

Цитата: Uukrul  link=topic=174.msg4062#msg4062 date=1244207259
Ну ты же сам написал... порядок полей в условии WHERE!!!, а какая разница есть справа значение для сравнения или нет?!

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


Паганель

Цитата: Martha від Липень 29, 2009, 11:52:49 ДП
этот порядок полей должен соответствовать порядку следования полей в индексе, который вы предполагаете, здесь будет использован или чему-то другому



Это вопрос?

Если да, то порядок не знаю, но наличие полей и значений - да.

Uukrul

Цитата: Martha від Липень 29, 2009, 11:52:49 ДП
этот порядок полей должен соответствовать порядку следования полей в индексе
Причем в индексе если таблица мандантно-зависимая, то обязательно должно быть включено поле манданта. Или иначе надо в запросе явно указывать что мандант не использовать.

Паганель

Цитата: Uukrul  link=topic=174.msg4566#msg4566 date=1248859657
Причем в индексе если таблица мандантно-зависимая, то обязательно должно быть включено поле манданта. Или иначе надо в запросе явно указывать что мандант не использовать.

Пример, или подробнее можно?

Martha

Цитата: Паганель від Липень 29, 2009, 11:55:43 ДП
Это вопрос?

Если да, то порядок не знаю, но наличие полей и значений - да.

У нас есть таблица  t1 в которой помимо ключа, есть индекс по полям f1, f3,f6, f7.

Есть
select  *  from t1
where f7  = z7  and f1 = z1 and f6 = z6 and f3 = z3.

Есть ли разница в скорости работы в том, в какой последовательности перечислены поля в where, если в индексе они идут – см выше.

SMF spam blocked by CleanTalk