Автор Тема: Оптимизация ABAP-а  (Прочитано 212245 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Uukrul

  • SAP ECC 6.0 Ehp(*)
  • Administrator
  • Epic Member
  • *****
  • Сообщений: 3 728
  • Репутация: +47/-0
  • Пол: Мужской
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
    • Sapforum.BIZ
Re: Оптимизация ABAP-а
« Ответ #175 : Сентябрь 21, 2011, 04:49:03 pm »
You are not allowed to view links. Register or Login
Всё пишешь, брат... 8)
Ну настоящему джентльмену всегда есть что по чем сказать  :P

Оффлайн Uukrul

  • SAP ECC 6.0 Ehp(*)
  • Administrator
  • Epic Member
  • *****
  • Сообщений: 3 728
  • Репутация: +47/-0
  • Пол: Мужской
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
    • Sapforum.BIZ
Re: Оптимизация ABAP-а
« Ответ #176 : Сентябрь 22, 2011, 10:50:23 am »
You are not allowed to view links. Register or Login
Кросавцег, что тут скажешь! Медведа меняй. :P

Оффлайн err

  • Newbie
  • *
  • Сообщений: 1
  • Репутация: +0/-0
  • Пол: Мужской
  • YearsYearsYearsYearsYearsYearsYearsYears
Re: Оптимизация ABAP-а
« Ответ #177 : Ноябрь 09, 2011, 12:24:15 pm »
БОЛЬШОЕ Спасибо за документ по оптимизации... Было очень познавательно почитать и почерпнуть мудрость.

Хотелось бы внести некоторые доработки в пример e8 (страница 32):
 - перевести алгоритм на field-symbol
 - использовать временный буфер на одну строку //занимаюсь BI и там достаточно часто возникает ситуация, что данные идут последовательно. Хотя в общем случае, из серии, повезет\неповезет
 - буферизировать ситуацию, когда в таблице в которой делаем select single запись не будет найдена //да я понимаю, что в примере не найти что то в t006 - это больше смахивает на какую то исключительную ситуацию, но в общем случае  это полезно

Итак E9

Код: You are not allowed to view links. Register or Login
DATA:
  l_rowbuffer     TYPE i.

FIELD-SYMBOLS:
  <ls_mseg_short> LIKE LINE OF lt_mseg_short
  <ls_t006a> TYPE t006a .

LOOP AT lt_mseg_short
    ASSIGNING <ls_mseg_short>.

    l_rowbuffer = 0.
    IF <ls_t006a> IS ASSIGNED.
        IF <ls_t006a>-msehi = <ls_mseg_short>-meins AND
            <ls_t006a>-spras = sy-lang.
            l_rowbuffer = 1.
        ENDIF.
    ENDIF.

    IF l_rowbuffer = 0.
        READ TABLE lt_t006a INTO ls_t006a
          WITH KEY msehi = <ls_mseg_short>-meins
          BINARY SEARCH.

        IF sy-subrc <> 0.
             SELECT SINGLE msehi mseht msehl INTO ls_t006a
             FROM t006a WHERE spras = sy-langu AND
             msehi = <ls_mseg_short>-meins.

             IF sy-subrc <> 0.
                 CLEAR: ls_t006a.
                 ls_t006a-spras = sy-lang.
                 ls_t006a-msehi = <ls_mseg_short>-meins.
             ENDIF.

             INSERT ls_t006a INTO lt_t006a INDEX sy-tabix
                 ASSIGNING <ls_t006a>.
        ENDIF.
    ENDIF.

    <ls_mseg_short>-mseht = <ls_t006a>-mseht.
    <ls_mseg_short>-msehl = <ls_t006a>-msehl.

ENDLOOP.

p.s. Вроде ошибок в коде не сделал... но если что не пинайте сильно...


Да, ещё почему то не отображаются картинки в скаченном файле Оптимизация ABAP v1-2.pdf
Рисунок 11: INDEX-TBL-1.png
Рисунок 12: Index-Tree-1.png

Оффлайн Uukrul

  • SAP ECC 6.0 Ehp(*)
  • Administrator
  • Epic Member
  • *****
  • Сообщений: 3 728
  • Репутация: +47/-0
  • Пол: Мужской
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
    • Sapforum.BIZ
Re: Оптимизация ABAP-а
« Ответ #178 : Ноябрь 09, 2011, 12:40:05 pm »
You are not allowed to view links. Register or Login
БОЛЬШОЕ Спасибо за документ по оптимизации... Было очень познавательно почитать и почерпнуть мудрость.
Да не за что... заходите вносите предложения. Ваш пример проверим и добавим. Спасибо за замечания.

You are not allowed to view links. Register or Login
Рисунок 11: INDEX-TBL-1.png
Рисунок 12: Index-Tree-1.png
Проверю...

Оффлайн Uukrul

  • SAP ECC 6.0 Ehp(*)
  • Administrator
  • Epic Member
  • *****
  • Сообщений: 3 728
  • Репутация: +47/-0
  • Пол: Мужской
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
    • Sapforum.BIZ
Re: Оптимизация ABAP-а
« Ответ #179 : Ноябрь 15, 2011, 12:52:57 am »
You are not allowed to view links. Register or Login
Да, ещё почему то не отображаются картинки в скаченном файле Оптимизация ABAP v1-2.pdf
Рисунок 11: INDEX-TBL-1.png
Рисунок 12: Index-Tree-1.png
Причина в том, что при передаче в PDF я эти две диаграммы не преобразовал из Visio в картинку и поэтому при сборке файла в PDF ничего не попало. В общем скоро выложу чуть дополненную очередную подверсию 1.3 где это уже будет исправлено.

Оффлайн mulyukov_am

  • Newbie
  • *
  • Сообщений: 27
  • Репутация: +0/-0
  • YearsYearsYearsYearsYearsYearsYears
Re: Оптимизация ABAP-а
« Ответ #180 : Июль 27, 2012, 06:33:53 am »
Большое спасибо авторам статьи. Оочень полезно.

Оффлайн A.

  • Newbie
  • *
  • Сообщений: 110
  • Репутация: +1/-0
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYears
Re: Оптимизация ABAP-а
« Ответ #181 : Декабрь 17, 2012, 02:20:38 pm »
Оптимизация ABAP v1-2.pdf, стр. 15, f6). Вопрос: зачем используется вторичная рабочая область *mseg в подзапросе?

Оффлайн Uukrul

  • SAP ECC 6.0 Ehp(*)
  • Administrator
  • Epic Member
  • *****
  • Сообщений: 3 728
  • Репутация: +47/-0
  • Пол: Мужской
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
    • Sapforum.BIZ
Re: Оптимизация ABAP-а
« Ответ #182 : Декабрь 17, 2012, 02:30:35 pm »
You are not allowed to view links. Register or Login
Оптимизация ABAP v1-2.pdf, стр. 15, f6). Вопрос: зачем используется вторичная рабочая область *mseg в подзапросе?
Это к Дмитрию вопрос  8)
Код: You are not allowed to view links. Register or Login
SELECT mseg~mblnr mseg~mjahr mseg~zeile mseg~bwart mseg~xauto
mseg~matnr mseg~werks mseg~lgort mseg~insmk mseg~shkzg
mseg~dmbtr mseg~bwtar mseg~menge mseg~bustm mkpf~budat
INTO TABLE lt_mseg
FROM mseg
JOIN mkpf ON mkpf~mblnr = mseg~mblnr AND
mkpf~mjahr = mseg~mjahr
WHERE mseg~matnr IN s_matnr
AND mseg~werks IN s_werks
AND mseg~lgort IN s_lgort
AND mseg~sobkz = ' '
AND mseg~smbln = ' '
AND mkpf~budat IN r_date
AND NOT EXISTS ( SELECT * FROM *mseg WHERE smbln = mseg~mblnr
AND sjahr = mseg~mjahr
AND smblp = mseg~zeile ).

Оффлайн A.

  • Newbie
  • *
  • Сообщений: 110
  • Репутация: +1/-0
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYears
Re: Оптимизация ABAP-а
« Ответ #183 : Декабрь 17, 2012, 02:42:04 pm »
стр. 18:
Цитировать
Примечание: В данном случае, при чтении данных в операторе READ TABLE не
использовалось расширение BINARY SEARCH, так как таблица lt_t006a не была объявлена
как сортированная, а для не сортированных данных, использовать такой поиск нельзя.
Более подробно о том, как идет выбор данных, из внутренних таблиц, рассмотрим в
части, где будет описаны способы объявления таких таблиц.
Как-то нечётко. Binary search как раз можно применять для таблиц, объявленных как standard, и для которых выполнена предварительная сортировка по нужным полям. Применение этого оператора для таблиц, объявленных как sorted, смысла не имеет, т.к. при указании полного ключа (либо выровненных по левому краю полей полного ключа) будет использоваться бинарный поиск, в противном случае - полный перебор, повлиять на него невозможно.

Оффлайн A.

  • Newbie
  • *
  • Сообщений: 110
  • Репутация: +1/-0
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYears
Re: Оптимизация ABAP-а
« Ответ #184 : Декабрь 17, 2012, 02:55:49 pm »
стр. 19:
Цитировать
Обрабатываются все SAP блокировки, установленные в текущей программе по
значению формального параметра _SCOPE для соответствующих функций
блокирования, происходит снятие таких блокировок.
Снятие блокировок типа 1 и 3 не происходит после commit work, они снимаются только при выходе из программы либо с помощью DEQUEUE_<enq_obj> (DEQUEUE_ALL). Тип 3 ставит две блокировки - одну для модулей обновления вида V1, вторую - внутри программы, для локальных обновлений, например. Для типа 2 блокировка не снимается, если модуль обновления не вызван.

Оффлайн Dmitriy

  • SAP ECC 6.0
  • Кухня
  • Newbie
  • *
  • Сообщений: 380
  • Репутация: +0/-0
  • Пол: Мужской
  • Embracive Fire
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
Re: Оптимизация ABAP-а
« Ответ #185 : Декабрь 17, 2012, 05:35:59 pm »
You are not allowed to view links. Register or Login
Оптимизация ABAP v1-2.pdf, стр. 15, f6). Вопрос: зачем используется вторичная рабочая область *mseg в подзапросе?
Давно дело было... Выборка без подзапроса и последующим циклом по внутренней с выборкой SELECT SINGLE из MSEG (с удалением сторно) заняла больше времени, чем указанная конструкция (больше миллионов позиций mseg). Не рекомендую так делать, сторно по другому удаляется. На одном проекте только удалось такое увидеть.

Оффлайн A.

  • Newbie
  • *
  • Сообщений: 110
  • Репутация: +1/-0
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYears
Re: Оптимизация ABAP-а
« Ответ #186 : Декабрь 17, 2012, 08:35:50 pm »
You are not allowed to view links. Register or Login
Не рекомендую так делать, сторно по другому удаляется. На одном проекте только удалось такое увидеть.
А какие будут рекомендации? Насколько я помню, для ММ в документе сторно заполняется ссылка на изначальный документ, а вот в изначальном соответствующей перекрёстной ссылки нет.

Оффлайн Uukrul

  • SAP ECC 6.0 Ehp(*)
  • Administrator
  • Epic Member
  • *****
  • Сообщений: 3 728
  • Репутация: +47/-0
  • Пол: Мужской
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
    • Sapforum.BIZ
Re: Оптимизация ABAP-а
« Ответ #187 : Декабрь 17, 2012, 09:57:00 pm »
You are not allowed to view links. Register or Login
А какие будут рекомендации?
Ну вот это и была рекомендация, как быстро обработать такую ситуацию. Еще как вариант в экзите ловить операцию сторно и делать отметку в первичном документе. Для быстрого исключения сторнированных документов.

Оффлайн A.

  • Newbie
  • *
  • Сообщений: 110
  • Репутация: +1/-0
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYears
Re: Оптимизация ABAP-а
« Ответ #188 : Декабрь 17, 2012, 10:02:05 pm »
А, я просто подумал, что прогресс двинулся ещё дальше :)
В одном из проектов была Z-табличка, если я всё правильно помню.

Ещё хотел бы сказать, что есть орфографические и пунктуационные ошибки в тексте. Не принципиально для смысла, но режет глаз. И шрифт ужасный - строчная наклонная "и" ненормальная :)

Оффлайн Dmitriy

  • SAP ECC 6.0
  • Кухня
  • Newbie
  • *
  • Сообщений: 380
  • Репутация: +0/-0
  • Пол: Мужской
  • Embracive Fire
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
Re: Оптимизация ABAP-а
« Ответ #189 : Декабрь 17, 2012, 10:34:30 pm »
You are not allowed to view links. Register or Login
Насколько я помню, для ММ в документе сторно заполняется ссылка на изначальный документ, а вот в изначальном соответствующей перекрёстной ссылки нет.
В MSEG, по индексу (номеру и год сторно) можно выбрать сторно изначальных.

Оффлайн Uukrul

  • SAP ECC 6.0 Ehp(*)
  • Administrator
  • Epic Member
  • *****
  • Сообщений: 3 728
  • Репутация: +47/-0
  • Пол: Мужской
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
    • Sapforum.BIZ
Re: Оптимизация ABAP-а
« Ответ #190 : Декабрь 17, 2012, 11:26:22 pm »
You are not allowed to view links. Register or Login
Ещё хотел бы сказать, что есть орфографические и пунктуационные ошибки в тексте. Не принципиально для смысла, но режет глаз. И шрифт ужасный - строчная наклонная "и" ненормальная :)
Ну это конвертация так в PDF проходит с  И, хотя у меня показывает нормально, но у меня дебиан, так что вполне может быть под виндой чуток по другому выглядит. Ошибки, подправим, но лучше конечно или мне отдельно на почту или тут написать. Остальные замечания то же учтем... если не очень поздно  8)

Оффлайн A.

  • Newbie
  • *
  • Сообщений: 110
  • Репутация: +1/-0
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYears
Re: Оптимизация ABAP-а
« Ответ #191 : Декабрь 18, 2012, 02:06:38 pm »
стр. 38, f8):
Цитировать
READ TABLE itab TRANSPORTING NO FIELDS
WITH KEY bukrs = '1000'
belnr = '5500000000'
BINARY SEARCH.
LOOP AT itab ASSIGNING <itab> FROM sy-tabix.
IF <itab>-belnr+0(2) <> '55'.
EXIT.
ENDIF.
ENDLOOP.

Таблица itab уже объявлена как sorted, здесь используется выровненный по левому краю ключ из двух полей - binary search не нужно. g8), h8) - аналогично.

Оффлайн Dmitriy

  • SAP ECC 6.0
  • Кухня
  • Newbie
  • *
  • Сообщений: 380
  • Репутация: +0/-0
  • Пол: Мужской
  • Embracive Fire
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
Re: Оптимизация ABAP-а
« Ответ #192 : Декабрь 18, 2012, 06:56:13 pm »
You are not allowed to view links. Register or Login
Это к Дмитрию вопрос  8)
Код: You are not allowed to view links. Register or Login
SELECT mseg~mblnr mseg~mjahr mseg~zeile mseg~bwart mseg~xauto
mseg~matnr mseg~werks mseg~lgort mseg~insmk mseg~shkzg
mseg~dmbtr mseg~bwtar mseg~menge mseg~bustm mkpf~budat
INTO TABLE lt_mseg
FROM mseg
JOIN mkpf ON mkpf~mblnr = mseg~mblnr AND
mkpf~mjahr = mseg~mjahr
WHERE mseg~matnr IN s_matnr
AND mseg~werks IN s_werks
AND mseg~lgort IN s_lgort
AND mseg~sobkz = ' '
AND mseg~smbln = ' '
AND mkpf~budat IN r_date
AND NOT EXISTS ( SELECT * FROM *mseg WHERE smbln = mseg~mblnr
AND sjahr = mseg~mjahr
AND smblp = mseg~zeile ).
Рекомендую измерить. Вопрос к пытливым умам и просто знающим людям.
Код: You are not allowed to view links. Register or Login
  TYPES: BEGIN OF t1,
    mblnr TYPE mblnr,
    mjahr TYPE mjahr,
    zeile TYPE mblpo,
    bwart TYPE bwart,
    matnr TYPE matnr,
    werks TYPE werks_d,
    lgort TYPE lgort_d,
    lifnr TYPE lifnr,
    menge TYPE menge_d,
    meins TYPE meins,
           END OF t1.

  DATA: lt_mseg TYPE STANDARD TABLE OF t1,
        lt_bkpf TYPE STANDARD TABLE OF bkpf.
  DATA: t1 TYPE i,
        t2 TYPE i,
        t_prev TYPE i,
        t_next TYPE i.
  DATA: delta TYPE p DECIMALS 3.
  DATA: lv1 TYPE n LENGTH 10,
        lv2 TYPE n LENGTH 10.
  DATA: ls_mseg TYPE t1.
  FIELD-SYMBOLS: <l> TYPE t1.

  GET RUN TIME FIELD t_prev.
  SELECT mseg~mblnr
         mseg~mjahr
         mseg~zeile
         mseg~bwart
         mseg~matnr
         mseg~werks
         mseg~lgort
         mseg~lifnr
         mseg~menge
         mseg~meins INTO TABLE lt_mseg FROM mseg JOIN mkpf
                                                   ON mkpf~mblnr = mseg~mblnr
                                                  AND mkpf~mjahr = mseg~mjahr
    WHERE mseg~matnr IN s_matnr
      AND mseg~werks IN s_werks
      AND mseg~lgort IN s_lgort
      AND mseg~sobkz = ' '
      AND mseg~smbln = ' '
      AND mkpf~mjahr EQ p_mjahr
      AND mkpf~budat IN s_budat.
  LOOP AT lt_mseg ASSIGNING <l>.
    SELECT SINGLE mblnr INTO ls_mseg-mblnr FROM mseg WHERE smbln = <l>-mblnr
                                                       AND sjahr = <l>-mjahr
                                                       AND smblp = <l>-zeile.
    IF sy-subrc = 0.
      DELETE lt_mseg.
    ENDIF.
  ENDLOOP.
  GET RUN TIME FIELD t_next.
  t1 = t_next - t_prev.
  lv1 = lines( lt_mseg ).

* Сброс предыдущего плана запроса
  SELECT mblnr
         mjahr
         zeile
         bwart
         matnr
         werks
         lgort
         lifnr
         menge
         meins INTO TABLE lt_mseg FROM mseg WHERE mblnr = '4900364642'.
  FREE lt_mseg.
* Забиваем кэш БД "левыми" данными
  SELECT * INTO TABLE lt_bkpf FROM bkpf WHERE bukrs = '1000' AND gjahr = '2012'.
  FREE lt_bkpf.

  GET RUN TIME FIELD t_prev.
  SELECT mseg~mblnr
         mseg~mjahr
         mseg~zeile
         mseg~bwart
         mseg~matnr
         mseg~werks
         mseg~lgort
         mseg~lifnr
         mseg~menge
         mseg~meins INTO TABLE lt_mseg FROM mseg JOIN mkpf
                                                   ON mkpf~mblnr = mseg~mblnr
                                                  AND mkpf~mjahr = mseg~mjahr
    WHERE mseg~matnr IN s_matnr
      AND mseg~werks IN s_werks
      AND mseg~lgort IN s_lgort
      AND mseg~sobkz = ' '
      AND mseg~smbln = ' '
      AND mkpf~mjahr EQ p_mjahr
      AND mkpf~budat IN s_budat
      AND NOT EXISTS ( SELECT * FROM *mseg WHERE smbln = mseg~mblnr
                                             AND sjahr = mseg~mjahr
                                             AND smblp = mseg~zeile ).
  GET RUN TIME FIELD t_next.
  t2 = t_next - t_prev.
  lv2 = lines( lt_mseg ).
  FREE lt_mseg.
*------------------------------------------------------------------------
* Коэффициент
  delta = t2 / t1.
  WRITE: 'Выборка № 1', t1, 'mks', lv1, 'lines',
       / 'Выборка № 2', t2, 'mks', lv2, 'lines',
       / 'Дельта'(008), delta.
При объемах выборки из MSEG ~ 1 млн. позиций увеличение скорости выборки-обработки при использовании AND NOT EXISTS варьировалось в пределах 1,3 - 4 раза. Что-то не так, наверное, я опять делаю?..

UPD: ограничивал годом и заводом                 
« Последнее редактирование: Декабрь 19, 2012, 01:54:39 pm от Dmitriy »

Оффлайн A.

  • Newbie
  • *
  • Сообщений: 110
  • Репутация: +1/-0
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYears
Re: Оптимизация ABAP-а
« Ответ #193 : Декабрь 19, 2012, 03:50:20 pm »
Вопрос такой, идея подхода - если заменять for all entries на создание индекса по нужным полям, в условии where указывать диапазон значений для каждого поля от и до, предварительно определив их.

Кто-нибудь пробовал? Стоит того?

Оффлайн Uukrul

  • SAP ECC 6.0 Ehp(*)
  • Administrator
  • Epic Member
  • *****
  • Сообщений: 3 728
  • Репутация: +47/-0
  • Пол: Мужской
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
    • Sapforum.BIZ
Re: Оптимизация ABAP-а
« Ответ #194 : Декабрь 19, 2012, 04:10:43 pm »
You are not allowed to view links. Register or Login
Вопрос такой, идея подхода - если заменять for all entries на создание индекса по нужным полям
Вообще-то на сколько я знаю такой операции как for all entries в языке SQL нет, это расширение языка абап которое транслируется вроде как в подзапросы, поэтому построение индекса по любому должно ускорить выбор вроде как.

Оффлайн Dmitriy

  • SAP ECC 6.0
  • Кухня
  • Newbie
  • *
  • Сообщений: 380
  • Репутация: +0/-0
  • Пол: Мужской
  • Embracive Fire
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
Re: Оптимизация ABAP-а
« Ответ #195 : Декабрь 19, 2012, 04:49:27 pm »
You are not allowed to view links. Register or Login
Вопрос такой, идея подхода - если заменять for all entries на создание индекса по нужным полям, в условии where указывать диапазон значений для каждого поля от и до, предварительно определив их.

Кто-нибудь пробовал? Стоит того?
Предлагаю попробовать и измерить, как раз как 3-й вариант выборки, в дополнение к коду выше.
Кстати, где-то в теме (и в документе .pdf) есть рекомендации про доп. ограничения, по моему там, где объясняется почему в условии иногда невыгоден оператор "<>". Т.е. смысл в том, чтобы "попасть" в индексы, когда нет ключа или он не полон.
Индекс № 1:
Код: You are not allowed to view links. Register or Login
MANDT
MATNR
WERKS
LGORT
BWART
SOBKZ
Индекс № 2:
Код: You are not allowed to view links. Register or Login
SMBLN
SJAHR
SMBLP
Можно учесть сторно по виду движения BWART, если предварительно созданы (или считываются стандартные) настройки, тогда сразу же за 1 выборку в одну вн. таблицу можно взять и исходные и сторно и затем в цикле работать уже со внутренней, к которой можно, допустим, объявить несколько ключей (прямой-сторно) ... Где и как взять виды движений сторно к "прямым" толковые ММ-щики знают. ;)   

Оффлайн Uukrul

  • SAP ECC 6.0 Ehp(*)
  • Administrator
  • Epic Member
  • *****
  • Сообщений: 3 728
  • Репутация: +47/-0
  • Пол: Мужской
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
    • Sapforum.BIZ
Re: Оптимизация ABAP-а
« Ответ #196 : Июнь 17, 2013, 12:02:01 pm »
Для немного оживления тем, ну и как небольшой анонс из будущего, небольшая заметка: Копирование данных внутренних таблиц - TABLE SHARING

При копировании данных из одной таблицы в другую для различных последующих обработок следует избегать конструкций вида IT_DATA2[] = IT_DATA1[]. Вместо этого лучше скопировать только действительно нужные записи в таблицу IT_DATA2. По скорости копирования вариант IT_DATA2[] тождествен варианту IT_DATA1[]. В определённых случаях этот способ - самый быстрый (если таблица-приёмник имеет более общий тип, чем таблица-источник), как видим копирование данных «таблица 1» = «таблица 2» по времени выполняется практически мгновенно (1), в отличие от копирования данных в цикле LOOP <…> ENDLOOP (2).

ВремВып: 4 микросек.
1)   gt_alvtab = gt_alvtab2.

ВремВып: 32.226 микросек.
2)   LOOP AT gt_alvtab2 ASSIGNING <fs_alvtab>.
           APPEND <fs_alvtab> TO gt_alvtab.
      ENDLOOP.

В примере 1 копирование происходит быстро по причине автоматического выполнения процедуры совместного использования данных внутренних таблиц – TABLE SHARING. Суть совместного использования данных заключается в том, что на самом деле копирования данных не происходит, система только создает заголовок таблицы приемника, который ссылается на те же самые страницы данных, что и таблица источник.

ВремВып: 28 микросек. – копирование таблица - таблица
3)   DATA: it_data1 TYPE TABLE OF mseg,
            it_data2 TYPE TABLE OF mseg.

      SELECT * INTO TABLE it_data1
      FROM mseg.
      it_data2 = it_data1.

При таком использовании система фактически не будет создавать страниц данных для внутренней таблицы IT_DATA2, а будет использовать ссылку в заголовке на страницы данных внутренней таблицы IT_DATA1.   Схематично это представлено на рисунке TBL_SHARING.png.

Такое совместное использование данных возможно только в случае если таблица-приёмник имеет более общий тип, чем таблица-источник, т. е. для случаев:
•   Таблицы - источник и приемник - объявлены одинаково, т. е. стандартная таблица копируется в стандартную или сортированная в сортированную, при этом обе таблицы объявлены с одинаковыми ключами.
•   Сортированная таблица копируется в стандартную таблицу
•   Хеш-таблица копируется в стандартную таблицу
•   Сортированная таблица с уникальными ключами копируется в сортированную таблицу, объявленную без уникальных ключей.

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

PS: В профиле системы, переменная abap/table_sharing должна быть установлена как on, это кстати обычно по умолчанию так, но ваш базис может случайно и отключить эту возможность.

Оффлайн kernel

  • Newbie
  • *
  • Сообщений: 10
  • Репутация: +0/-0
  • YearsYearsYears
Re: Оптимизация ABAP-а
« Ответ #197 : Июнь 30, 2016, 06:43:46 am »
Внесу свое дополнение по оптимизации j6 на стр. 17.
1. Использовать символьные ссылки
2. Таблицу lt_t006a объявить как хэш-таблицу с уникальным ключом msehi. И работать как с хэш-таблицей.
Код: You are not allowed to view links. Register or Login
DATA lt_t006a LIKE HASHED TABLE OF ls_t006a WITH UNIQUE KEY msehi.
...
LOOP AT lt_mseg_short ASSIGN <ls_mseg_short>.
  READ TABLE lt_t006a INTO ls_t006a  WITH TABLE KEY msehi = <ls_mseg_short>-meins.
  IF sy-subrc <> 0.
    SELECT SINGLE msehi mseht msehl
      INTO ls_t006a
      FROM t006a
      WHERE spras = sy-langu AND
            msehi = <ls_mseg_short>-meins.
    IF sy-subrc <> 0.
      CONTINUE.
    ENDIF.

    INSERT ls_t006a INTO TABLE lt_t006a.
  ENDIF.
 
  <ls_mseg_short>-mseht = ls_t006a-mseht.
  <ls_mseg_short>-msehl = ls_t006a-msehl.
ENDLOOP.

P.S: писал по памяти, без проверки.

В тему:
1. Есть удобная обертка для данной задачи You are not allowed to view links. Register or Login
2. Похожая обертка, использующая INSERT REPORT You are not allowed to view links. Register or Login

Оффлайн Uukrul

  • SAP ECC 6.0 Ehp(*)
  • Administrator
  • Epic Member
  • *****
  • Сообщений: 3 728
  • Репутация: +47/-0
  • Пол: Мужской
  • YearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYearsYears
    • Sapforum.BIZ
Re: Оптимизация ABAP-а
« Ответ #198 : Июнь 30, 2016, 11:20:25 am »
You are not allowed to view links. Register or Login
2. Таблицу lt_t006a объявить как хэш-таблицу с уникальным ключом msehi. И работать как с хэш-таблицей.
Вот тут не согласен, в этой таблице в общем случае будет ну пусть 20 единиц измерения, SAP для таких таблиц вообще не рекомендует использовать хэш-таблицы, так как накладные расходы на ведение B-дерева будут больше чем вообще просто фулсканом проходить эти 20 записей. Так что тут или цифры в студию или верим рекомендациям разработчика системы, который говорит что хэш-таблицы объявляйте для таблиц с большим количеством данных, а единицы измерения ну никак не попадают под этот критерий.

Оффлайн kernel

  • Newbie
  • *
  • Сообщений: 10
  • Репутация: +0/-0
  • YearsYearsYears
Re: Оптимизация ABAP-а
« Ответ #199 : Июль 02, 2016, 09:00:17 pm »
В случае с ЕИ согласен, стандартная таблица работает незначительно быстрее. Но если заполнять, например, наименования материалов, то разница будет очень ощутима. Ниже результаты теста и листинг.

Всего записей в таблице - 225.577
Уникальных ЕИ - 19
Уникальных материалов - 12.830

Время выполнения
75.346.455   Perform FILL_MAKTX_TEST_STANDARD
 7.808.434   Perform FILL_MAKTX_TEST_SORTED
 6.117.128   Perform FILL_MAKTX_TEST_HASHED
 5.972.692   Perform FILL_MSEHL_TEST_SORTED
 5.771.199   Perform FILL_MSEHL_TEST_HASHED
 5.347.074   Perform FILL_MSEHL_TEST_STANDARD

Листинг
Код: You are not allowed to view links. Register or Login
REPORT  z_read_table_test.

DATA:
  BEGIN OF gt_table OCCURS 0,
    matnr TYPE matnr,
    maktx TYPE maktx,
    meins TYPE meins,
    msehl TYPE msehl,
  END OF gt_table,
  gt_t006a TYPE STANDARD TABLE OF t006a,
  gt_makt TYPE STANDARD TABLE OF makt.

FIELD-SYMBOLS:
<wa_table> LIKE LINE OF gt_table,
<wa_t006a> LIKE LINE OF gt_t006a,
<wa_makt> LIKE LINE OF gt_makt.

INITIALIZATION.

START-OF-SELECTION.
  PERFORM main.

*&---------------------------------------------------------------------*
*&      Form  main
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM main.
  SELECT *
    FROM t006a
    INTO TABLE gt_t006a
    WHERE spras EQ 'R'.

  SELECT *
    FROM makt
    INTO TABLE gt_makt
    WHERE spras EQ 'R'.

  SORT gt_t006a BY msehi.
  SORT gt_makt BY matnr.

  SELECT matnr meins
    INTO CORRESPONDING FIELDS OF TABLE gt_table
    FROM z_big_data_table
    WHERE gjahr GE 2010.

  DO 100 TIMES.
    PERFORM fill_msehl_test_standard.
    PERFORM fill_msehl_test_sorted.
    PERFORM fill_msehl_test_hashed.

    PERFORM fill_maktx_test_standard.
    PERFORM fill_maktx_test_sorted.
    PERFORM fill_maktx_test_hashed.
  ENDDO.
ENDFORM.                    "main

*&---------------------------------------------------------------------*
*&      Form  get_msehl
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->MEINS      text
*      -->MSEHL      text
*----------------------------------------------------------------------*
FORM get_msehl USING meins CHANGING msehl.
  READ TABLE gt_t006a WITH KEY msehi = meins ASSIGNING <wa_t006a> BINARY SEARCH.
  CHECK sy-subrc EQ 0.

  msehl = <wa_t006a>-msehl.
ENDFORM.                    "get_msehl

*&---------------------------------------------------------------------*
*&      Form  get_maktx
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->MATNR      text
*      -->MAKTX      text
*----------------------------------------------------------------------*
FORM get_maktx USING matnr CHANGING maktx.
  READ TABLE gt_makt WITH KEY matnr = matnr ASSIGNING <wa_makt> BINARY SEARCH.
  CHECK sy-subrc EQ 0.

  maktx = <wa_makt>-maktx.
ENDFORM.                    "get_maktx

*&---------------------------------------------------------------------*
*&      Form  fill_msehl_test_standard
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM fill_msehl_test_standard.
  DATA lt_t006a TYPE STANDARD TABLE OF t006a.
  DATA ls_t006a TYPE t006a.

  LOOP AT gt_table ASSIGNING <wa_table>.
    READ TABLE lt_t006a INTO ls_t006a WITH KEY msehi = <wa_table>-meins.
    IF sy-subrc <> 0.
      ls_t006a-msehi = <wa_table>-meins.
      PERFORM get_msehl USING ls_t006a-msehi CHANGING ls_t006a-msehl.
      IF sy-subrc <> 0.
        CLEAR ls_t006a-msehl.
      ENDIF.

      INSERT ls_t006a INTO TABLE lt_t006a.
    ENDIF.

    <wa_table>-msehl = ls_t006a-msehl.
  ENDLOOP.
ENDFORM.                    "fill_msehl_test_standard

*&---------------------------------------------------------------------*
*&      Form  fill_msehl_test_sorted
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM fill_msehl_test_sorted.
  DATA lt_t006a TYPE SORTED TABLE OF t006a WITH UNIQUE KEY msehi.
  DATA ls_t006a TYPE t006a.

  LOOP AT gt_table ASSIGNING <wa_table>.
    READ TABLE lt_t006a INTO ls_t006a WITH TABLE KEY msehi = <wa_table>-meins.
    IF sy-subrc <> 0.
      ls_t006a-msehi = <wa_table>-meins.
      PERFORM get_msehl USING ls_t006a-msehi CHANGING ls_t006a-msehl.
      IF sy-subrc <> 0.
        CLEAR ls_t006a-msehl.
      ENDIF.

      INSERT ls_t006a INTO TABLE lt_t006a.
    ENDIF.

    <wa_table>-msehl = ls_t006a-msehl.
  ENDLOOP.
ENDFORM.                    "fill_msehl_test_sorted

*&---------------------------------------------------------------------*
*&      Form  fill_msehl_test_hashed
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM fill_msehl_test_hashed.
  DATA lt_t006a TYPE HASHED TABLE OF t006a WITH UNIQUE KEY msehi.
  DATA ls_t006a TYPE t006a.

  LOOP AT gt_table ASSIGNING <wa_table>.
    READ TABLE lt_t006a INTO ls_t006a WITH TABLE KEY msehi = <wa_table>-meins.
    IF sy-subrc <> 0.
      ls_t006a-msehi = <wa_table>-meins.
      PERFORM get_msehl USING ls_t006a-msehi CHANGING ls_t006a-msehl.
      IF sy-subrc <> 0.
        CLEAR ls_t006a-msehl.
      ENDIF.

      INSERT ls_t006a INTO TABLE lt_t006a.
    ENDIF.

    <wa_table>-msehl = ls_t006a-msehl.
  ENDLOOP.
ENDFORM.                    "fill_msehl_test_hashed

*&---------------------------------------------------------------------*
*&      Form  fill_maktx_test_standard
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM fill_maktx_test_standard.
  DATA lt_makt TYPE STANDARD TABLE OF makt.
  DATA ls_makt TYPE makt.

  LOOP AT gt_table ASSIGNING <wa_table>.
    READ TABLE lt_makt INTO ls_makt WITH KEY matnr = <wa_table>-matnr.
    IF sy-subrc <> 0.
      ls_makt-matnr = <wa_table>-matnr.
      PERFORM get_maktx USING ls_makt-matnr CHANGING ls_makt-maktx.
      IF sy-subrc <> 0.
        CLEAR ls_makt-maktx.
      ENDIF.

      INSERT ls_makt INTO TABLE lt_makt.
    ENDIF.

    <wa_table>-maktx = ls_makt-maktx.
  ENDLOOP.
ENDFORM.                    "fill_maktx_test_standard

*&---------------------------------------------------------------------*
*&      Form  fill_maktx_test_sorted
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM fill_maktx_test_sorted.
  DATA lt_makt TYPE SORTED TABLE OF makt WITH UNIQUE KEY matnr.
  DATA ls_makt TYPE makt.

  LOOP AT gt_table ASSIGNING <wa_table>.
    READ TABLE lt_makt INTO ls_makt WITH TABLE KEY matnr = <wa_table>-matnr.
    IF sy-subrc <> 0.
      ls_makt-matnr = <wa_table>-matnr.
      PERFORM get_maktx USING ls_makt-matnr CHANGING ls_makt-maktx.
      IF sy-subrc <> 0.
        CLEAR ls_makt-maktx.
      ENDIF.

      INSERT ls_makt INTO TABLE lt_makt.
    ENDIF.

    <wa_table>-maktx = ls_makt-maktx.
  ENDLOOP.
ENDFORM.                    "fill_maktx_test_sorted

*&---------------------------------------------------------------------*
*&      Form  fill_maktx_test_hashed
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
FORM fill_maktx_test_hashed.
  DATA lt_makt TYPE HASHED TABLE OF makt WITH UNIQUE KEY matnr.
  DATA ls_makt TYPE makt.

  LOOP AT gt_table ASSIGNING <wa_table>.
    READ TABLE lt_makt INTO ls_makt WITH TABLE KEY matnr = <wa_table>-matnr.
    IF sy-subrc <> 0.
      ls_makt-matnr = <wa_table>-matnr.
      PERFORM get_maktx USING ls_makt-matnr CHANGING ls_makt-maktx.
      IF sy-subrc <> 0.
        CLEAR ls_makt-maktx.
      ENDIF.

      INSERT ls_makt INTO TABLE lt_makt.
    ENDIF.

    <wa_table>-maktx = ls_makt-maktx.
  ENDLOOP.
ENDFORM.                    "fill_maktx_test_hashed

Случай с ЕИ скорее исключение из правил. В моих отчетах, заказчик хочет видеть: наименования БЕ, заводов, групп материалов, материалов, складов, счетов, контрагентов, подразделений, и т.п. Во всех отчетах с 1000+ строк лучший результат по времени давала хэш-таблица.