Sapforum.Biz

Инструменты => ABAP - Инструментальные средства => Тема розпочата: Uukrul від Травень 16, 2008, 11:39:58 ДП

Назва: Оптимизация ABAP-а
Відправлено: Uukrul від Травень 16, 2008, 11:39:58 ДП
Данное первое сообщение темы будет содержать обобщенный документ по оптимизации ABAP.

25.10.2010 - Первая версия документа 1.0

21.03.2011 - Изменения к оптимизации ABAP версия 1.1
Цитата
Краткий список изменений:

  • Расширено описание пункта 8 – Определение внутренних таблиц, добавлен раздел 8.1 описывающий внутреннюю организацию и принципы выделения памяти системой для внутренних таблиц, так же описан параметр INITIAL SIZE используемый при объявлении внутренних таблиц в программах и общие рекомендации по его использованию.
  • Расширено описание пункта 8 – Определение внутренних таблиц, добавлен раздел 8.2 описывающий организацию индексов для внутренних таблиц и принципов их построения.
  • Расширено и изменено описание пункта 9, работа операторов REFRESH и FREE, в связи с получением более подробной информации по их функционированию.
  • Небольшие несущественные правки по тексту из-за внесенных выше изменений в раздел 8

21.09.2011 - Изменения к оптимизации ABAP версия 1.2
Цитата
Краткий список изменений:

  • Расширено описание пункта 10 – Тестирование программ, дополнено описание использования транзакций расширенной проверки программы SLIN и анализатора код транзакции SCI / SCII.

PS: Предыдущие версии документа, пока удаляться не будут...
PPS: И кстати качать предыдущие версии документа не обязательно, хотя если вы хотите отследить как менялось мое и всех кто помогал мне писать документ, представление об оптимизации ABAP-а, ну тогда да, качайте  ;D
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Травень 16, 2008, 11:50:20 ДП
В общем как не крутись а писать на ABAP приходится и очень часто это какие-то отчеты/обработки, которые гудят долго и жрут как памяти так и процессора много, в общем-то зубры и так знают как писать правильно, а вот молодЕжь такие перлы выдает, что иногда... хотя опять же если вспомнить прошлый век и свой первый отчет, то как говориться сам такой был. А поэтому предлагают тут поделиться примерами того как надо писать, чтобы или работало быстрее или памяти жрало меньше или.. ну в общем от ситуации.

PS: При этом не надо думать, что если что-то вам кажется общеизвестным, то это таки действительно общеизвестно  ;)

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

Выборка данных из таблиц.


DATA: lt_mara LIKE mara OCCURS 1 WITH HEADER LINE.

SELECT * INTO CORRESPONDIG FIELDS OF TABLE lt_mara
FROM mara

работает медленнее, чем
SELECT * INTO TABLE lt_mara
FROM mara


В общем случае время выполнения первого запроса раза в 4 больше чем второй вариант.
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Травень 16, 2008, 10:21:16 ПП
-- а что лутше select sum(xxx) from yyy или  ....

ЦитатаВ общем как не крутись а писать на ABAP приходится и очень часто это какие-то отчеты/обработк
-- ну вижу (у нас) то знание абап - только вред - так тебя начинают грузить программерской работой, никагого росту, за деревьями леса не видиш ....
а рядок девушки  - абпапа нифига - так у них и задачи поинтересней,  и загрузка полутше ...

p.s. может тему начать ? Типа консультант без знания абап, хорошо или плохо ....
или "Насколько большой недостаток - знать абап"
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Травень 16, 2008, 10:39:09 ПП
Цитата: "Паганель" від Травень 16, 2008, 10:21:16 ПП
-- а что лучше select sum(xxx) from yyy или  ....
Для больших таблиц... ну скажем так, как отрабатывает операция SUM(XXX), при такой конструкции всегда подразумевается что есть группа записей с одинаковым значением одного поля и числовым полем, т.е.

ID COST
------------
01 2
02 2
01 3
01 1
02 1

Без индекса к чему это ведет? А к тому что при операции суммирования, для каждого из значений ID в общем случае система пробегает по всей таблице, да кеширование и оптимизация при обработки SQL-запросов + индексы ускорят процесс, но в общем случае без индекса сумму для каждого ID можно получить выполнив для данного примера двойной проход по таблице, сначала для ID = 01, затем для ID = 02, а поэтому иногда может быть быстрее загрузить все во внутреннюю таблицу (если по памяти есть куда) и уже в памяти пройтись и просуммировать данные.

Опять же, все таки желательно смотреть на данные и уже из этого решать, что будет быстрее, т.е. запрос с суммированием или чтение SELECT * INTO TABLE xxx и уже затем LOOP AT lt_xxx. ENDLOOP. С суммированием в цикле.

Из личного опыта на большой таблице, >30 000 000 записей, но записи длинной порядка 100 байт, мне надо было посчитать не сумму, а количество записей с определенными ID. Так вот, операция SELECT COUNT(*) просто зависло и не вернулось из задумчивости, а вот вариант с выбором во внутреннюю таблицу и ручным суммированием, оказался очень даже быстрым и приемлимым. Индексы были построены и первый SELECT по плану запроса ходил как раз именно по индексу.

Цитата: "Паганель" від Травень 16, 2008, 10:21:16 ПП
а рядок девушки  - абпапа нифига - так у них и задачи поинтересней,  и загрузка полутше ...
p.s. может тему начать ? Типа консультант без знания абап, хорошо или плохо ....
или "Насколько большой недостаток - знать абап"
Ну открывай, в другой ветке конечно  ::)
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Травень 16, 2008, 11:10:29 ПП
Цитатауже в памяти пройтись и просуммировать данные.

Можеш пример в студию - простенький лиш бы понять смысл ?
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Травень 17, 2008, 12:07:40 ДП
Цитата: "Паганель" від Травень 16, 2008, 11:10:29 ПП
Можеш пример в студию - простенький лиш бы понять смысл ?
Так а чего там пример то? Ну схематично, без системы типа так:

*&---------------------------------------------------------------------*
*& Report  YUUK_TEST
*&
*&---------------------------------------------------------------------*
*& В общем пример суммы свободного запаса по заводам для материалов
*&
*&---------------------------------------------------------------------*

REPORT  yuuk_test.
DATA: BEGIN OF lt_mard OCCURS 1.
        INCLUDE STRUCTURE mard.
DATA: index LIKE sy-tabix,
END OF lt_mard.
DATA: l_mard LIKE lt_mard.

*--------------------------
SELECT * INTO TABLE lt_mard
FROM mard
ORDER BY werks matnr.

* Опять же может окажется что SORT lt_mard BY werks matnr.
* может быстрее быть чем сортировка в запросе. Тут надо смотреть
* на память и объемы выборки...

LOOP AT lt_mard.
  ON CHANGE OF lt_mard-werks OR lt_mard-matnr.
    IF sy-tabix = 1.
      lt_mard-index = sy-tabix.
      l_mard = lt_mard.
    ELSE.
      MODIFY lt_mard FROM l_mard INDEX l_mard-index.
      lt_mard-index = sy-tabix.
      l_mard = lt_mard.
    ENDIF.
    CONTINUE.
  ENDON.
  l_mard-labst = l_mard-labst + lt_mard-labst.
ENDLOOP.
IF lt_mard-index = 0.
  l_mard-labst = l_mard-labst + lt_mard-labst.
ENDIF.
MODIFY lt_mard FROM l_mard INDEX l_mard-index.

DELETE lt_mard WHERE index = 0.

LOOP AT lt_mard.
  WRITE: / lt_mard-werks, lt_mard-lgort, lt_mard-matnr, lt_mard-labst.
ENDLOOP.
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Травень 17, 2008, 12:17:07 ДП
Спасибо, что то такое я и думал ... только не мог вспомнить где видел подобное ...
Кажется аналогично делается отчет с суммами по группам с помощю WRITE ...

Вопрос: а зачем так
ЦитатаDELETE lt_mard WHERE index = 0.

Как я понял - для очистки строки (шапки таблицы) ...

А чего не clear ...  сейчас еще посмотрю ..ю
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Травень 17, 2008, 12:39:00 ДП
Цитата: "Паганель" від Травень 17, 2008, 12:17:07 ДП
Вопрос: а зачем так
Как я понял - для очистки строки (шапки таблицы) ...
Нет, конечно... я убираю из памяти лишние запаси которые уже вошли в суммирование... т.е. пример есть пять записей на двух заводах одного материала:

1000 0088 M1 1
1000 0001 M1 2
1000 0088 M1 5
1000 0010 M1 3
1200 0001 M1 4

Так вот после выборки с сортировкой я получу, ну пусть такой порядок:
1000 0001 M1 2
1000 0088 M1 5
1000 0088 M1 1
1000 0010 M1 3
1200 0001 M1 4

После обработки будет такая ситуация во внутренней таблице:
1000 0001 M1 11 1
1000 0088 M1 5 0
1000 0088 M1 1 0
1000 0010 M1 3 0
1200 0001 M1 4 5

Затем я оператом DELETE грохну нулевые индексы и получу
1000 0001 M1 11 1
1200 0001 M1 4 5

На склад забиваем и того имею суммы запасов материала по заводу в целом.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Травень 17, 2008, 12:48:08 ДП
Поля в примере идут:
Завод, Склад, Код материала, Количество

В результирующей выборке, последнее число, это индекс записи внутренней таблицы... из примера программы это поле index.
Назва: Re: Оптимизация ABAP-а (SELECT * ENDSELECT.)
Відправлено: Uukrul від Травень 19, 2008, 10:39:05 ДП
Самый тормознутый способ выборки чего либо из таблиц это операция:

SELECT * FROM mard.
ENDSELECT.

Однако исключать данный способ из применения не следует, так как он дает наименьшую нагрузку на сервер + минимальное использование памяти. Так что если таблица небольшая или выборка данных будет небольшой, то вполне можно обойтись и данной конструкцией, т.е. без операции SELECT * INTO TABLE и дальнейшим LOOP AT lt_tab. ENDLOOP.  Ну и как обычно смотрим трассировку запросов. Если эта конструкция является самой тормознутой в вашем приложении, то имеет смысл ее заменить, а иначе, нефиг заниматься оптимизацией так где и без нее все бегает  ;)
Назва: Re: Оптимизация ABAP-а
Відправлено: №1 від Травень 20, 2008, 09:11:11 ДП
Цитата: Uukrul від Травень 16, 2008, 11:39:58 ДП
PS: При этом не надо думать, что если что-то вам кажется общеизвестным, то это таки действительно общеизвестно  ;)
Добавлю свои пять копеек... про конструкцию SELECT .... FOR ALL ENTRIES IN itab
Если itab пустая, то будет перебор всей таблицы, т.е. FULL SCAN. Поэтому надо до оператора поставить проверку на непустоту.
ЗЫ. Непонятно одно - почему САПы не воткнули такую проверку на уровне ядра? Жить было бы куда проще.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Червень 22, 2008, 08:48:15 ПП
Ну поехали дальше (Опять же из обще известного, так сказать примеры из документации SAP, руки до которой почему-то у многих не доходят):

Требуется проверить на существование записи в таблице БД по определенному не полному ключу. Варианта тут есть два, первый делаем SELECT с нужными ключами и внутри EXIT.

SELECT * FROM <table> INTO <work_line>
    WHERE <Field> = 'xxx'.
  EXIT.
ENDSELECT.

или

SELECT * FROM <table> INTO <work_line>
  UP TO 1 ROWS
  WHERE <Field> = 'xxx'.
ENDSELECT.

Так вот второй вариант с UP TO 1 ROWS (кстати многие похоже о такой конструкции даже не подозревают), работает так раз в 6-7 быстрее, чем первый вариант.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Червень 22, 2008, 09:05:26 ПП
Ну и дальше возвращаясь к теме агрегирующих функций, собственно с чего началась данная тема, вообще-то документация советует использовать именно функции агрегации типа MAX, MIN, SUM и т.д. вместо использования построчного подсчета значений. В справке приведены такие два примера, по поиску максимального значения:


DATA: MAX_MSGNR type t100-msgnr.
MAX_MSGNR = '000'.
SELECT * FROM T100 INTO T100_WA
  WHERE SPRSL = 'D' AND
        ARBGB = '00'.
  CHECK: T100_WA-MSGNR > MAX_MSGNR.
  MAX_MSGNR = T100_WA-MSGNR.
ENDSELECT.

и

DATA: MAX_MSGNR type t100-msgnr.
SELECT MAX( MSGNR ) FROM T100 INTO max_msgnr
  WHERE SPRSL = 'D' AND
        ARBGB = '00'.

Разница в выполнении этих двух примеров где-то раз в 100, т.е. первый пример будет работать ну на много дольше. Однако если вернуться к конструкции UP TO 1 ROWS, то добавив конструкцию ORDER BY с соответсующей сортировке по убыванию  для MAX или по возрастанию для MIN получим время выполнения такое же как и в примере с агрегирующей функцией.  Пример ниже:

DATA: MAX_MSGNR type t100-msgnr.
MAX_MSGNR = '000'.

SELECT * FROM T100 INTO T100_WA UP TO 1 ROWS
  WHERE SPRSL = 'D' AND
        ARBGB = '00'
ORDER BY MSGNR DESCENDING.
ENDSELECT.

В общем замеры времени выполнения для примера 2 и 3 показали 81 и 85 миллисекунд (для примера 1, кстати было 7360), т.е.  для функций MIN и MAX, можно использовать альтернативу UP TO 1 ROWS совместно с ORDER BY. Ну а сумма и среднее значение, это уже по обстоятельствам надо смотреть  ;)
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Червень 22, 2008, 09:27:11 ПП
По поводу данных которые мы выбираем. В общем не следует без всякой необходимости использовать * в операторе SELECT, если вас интересует значение одного или пары полей из сотни, которые входят в таблицу. Пример из справки:

SELECT * FROM DD01L INTO DD01L_WA
  WHERE DOMNAME LIKE 'CHAR%'
        AND AS4LOCAL = 'A'.
ENDSELECT.

и

SELECT DOMNAME FROM DD01L
  INTO DD01L_WA-DOMNAME
  WHERE DOMNAME LIKE 'CHAR%'
        AND AS4LOCAL = 'A'.
ENDSELECT.

В первом случае  получаем время выполнения порядка 8285 миллисекунд, а во втором случае 2596. Ну т.е. где-то раза в 4.

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

DATA: MAX_MSGNR type t100-msgnr.

SELECT MSGNR FROM T100 INTO (MAX_MSGNR) UP TO 1 ROWS
  WHERE SPRSL = 'D' AND
        ARBGB = '00'
ORDER BY MSGNR DESCENDING.
ENDSELECT.

т.е. задав выбор только поля по которому требуется получить максимальное значение и после этого выполнение станет практически такое же как и с использованием функции MAX, у меня получилось после нескольких прогонов разница в 1-2 миллисекунды. В общем так как не ассемблер, то на эти миллисекунды уже можно и забить.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Червень 22, 2008, 09:37:56 ПП
Если имеются часто изменяемые данные в таблицах, например это очереди в таблице сообщений, то читают такие данные обычно с выключением буфера. Однако не следует этим перебарщивать, а то скорость обработки ясное дело будет печальной. Примеры из справки:

SELECT SINGLE * FROM T100 INTO T100_WA
  BYPASSING BUFFER
  WHERE     SPRSL = 'D'
        AND ARBGB = '00'
        AND MSGNR = '999'.

и

SELECT SINGLE * FROM T100  INTO T100_WA
  WHERE     SPRSL = 'D'
        AND ARBGB = '00'
        AND MSGNR = '999'.

В общем случае скорость для первого запроса ~80 миллисекунд, а во втором порядка 5 миллисекунд.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Червень 22, 2008, 09:49:02 ПП
Возвращаясь к вариантам выбора записей из таблиц и их последующей обработке есть два варианта, выбрать все и затем пройтись по внутренней таблице или же обрабатывать данные по мере из выбора внутри конструкции SELECT ENDSELECT. В общем случае быстрее будет выбрать данные во внутреннюю таблицу и затем обработать выборку. Примеры:

SELECT * FROM T006
  INTO TABLE X006.
LOOP AT X006 INTO X006_WA.
ENDLOOP.

и

SELECT * FROM T006 INTO X006_WA.
ENDSELECT.

Первый вариант работает быстрее в среднем в полтора-два раза чем вариант два. По замерам время исполнения в среднем колебалось 60 и 110 миллисекунд.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Червень 22, 2008, 10:01:11 ПП
Вложенные SELECT или SELECT с JOIN. Я вообще-то предпочитаю  использовать конструкцию JOIN хотя как показывают замеры, первый вариант работает быстрее. В общем случае констуркция

SELECT * FROM SPFLI INTO SPFLI_WA.
  SELECT * FROM SFLIGHT INTO SFLIGHT_WA
      WHERE CARRID = SPFLI_WA-CARRID
        AND CONNID = SPFLI_WA-CONNID.
  ENDSELECT.
ENDSELECT.

была быстрее чем конструкция

SELECT * INTO WA
    FROM SPFLI AS P JOIN SFLIGHT AS F
      ON P~CARRID = F~CARRID AND
         P~CONNID = F~CONNID.
ENDSELECT.

По времени выполнения  получается 6100 миллисекунд против 8300 во втором случае. Но пять же, требуется смотреть на таблицы из которых выбираются данные и на объем который требуется выбрать.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Червень 22, 2008, 10:10:18 ПП
Подзапросы или FOR ALL ENTRIES IN T_SPFLI с использованием двух операторов SELECT. Исходя из примера по справке, существуют следующие варианты выборки:

SELECT * FROM SPFLI
  INTO TABLE T_SPFLI
  WHERE CITYFROM = 'FRANKFURT'
    AND CITYTO = 'NEW YORK'.
SELECT * FROM SFLIGHT AS F
    INTO SFLIGHT_WA
    FOR ALL ENTRIES IN T_SPFLI
    WHERE SEATSOCC < F~SEATSMAX
      AND CARRID = T_SPFLI-CARRID
      AND CONNID = T_SPFLI-CONNID
      AND FLDATE BETWEEN '19990101' AND '19990331'.
ENDSELECT.

и

SELECT * FROM SFLIGHT AS F INTO SFLIGHT_WA
    WHERE SEATSOCC < F~SEATSMAX
      AND EXISTS ( SELECT * FROM SPFLI
                     WHERE CARRID = F~CARRID
                       AND CONNID = F~CONNID
                       AND CITYFROM = 'FRANKFURT'
                       AND CITYTO = 'NEW YORK' )
      AND FLDATE BETWEEN '19990101' AND '19990331'.
ENDSELECT.

В общем случае второй вариант работает быстрее, 210 простив 130 миллисекунд, чем использование FOR ALL ENTRIES.  Кстати по поводу FOR ALL ENTRIES, не забываем, что если табличка T_SPFLI, будет пустой, то как уже писал №1, будет полный проход таблицы.
Назва: Re: Оптимизация ABAP-а
Відправлено: bdmalex від Червень 27, 2008, 07:07:17 ПП
ВВерну свои 5 копеек...

Начиная с какой-то версии 4.x(точно не скажу) - есть прекрасный инструмент: Сode Inspector(Код инспектор)
...
IMHO - помогает бороться с ошибками(явными и не очень) ЛЮБЫХ абаперов...:)...
...
А вообще - инфа на курсах ADM315(немного) и BC490....
Назва: Re: Оптимизация ABAP-а
Відправлено: №1 від Червень 27, 2008, 08:04:31 ПП
Цитата: bdmalex від Червень 27, 2008, 07:07:17 ПП
прекрасный инструмент: Сode Inspector(Код инспектор)
Тада свой полтинник... от избыточных выборок по базе это чудо бессильно 8)
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Липень 01, 2008, 05:52:49 ПП
Цитата: bdmalex від Червень 27, 2008, 07:07:17 ПП
Начиная с какой-то версии 4.x(точно не скажу) - есть прекрасный инструмент: Сode Inspector(Код инспектор)
Это транзакция SLIN имеется в виду?
Назва: Re: Оптимизация ABAP-а
Відправлено: №1 від Липень 01, 2008, 06:09:49 ПП
Цитата: Uukrul від Липень 01, 2008, 05:52:49 ПП
Это транзакция SLIN имеется в виду?
SCI
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Липень 01, 2008, 06:38:58 ПП
Цитата: №1 від Липень 01, 2008, 06:09:49 ПП
SCI
Чего-то в 4.6С сказало нет такой буквы...
Назва: Re: Оптимизация ABAP-а
Відправлено: №1 від Липень 01, 2008, 07:43:45 ПП
А в 4.6С надо отдельным транспортом это тащить - есть нота
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Липень 02, 2008, 09:36:22 ДП
Цитата: №1 від Липень 01, 2008, 07:43:45 ПП
А в 4.6С надо отдельным транспортом это тащить - есть нота
А номерок ноты? А то я что-то не нашел, о разных исправлениях ошибок есть... а саму программку где тянуть не находиться...
Назва: Re: Оптимизация ABAP-а
Відправлено: №1 від Липень 02, 2008, 09:52:12 ДП
Цитата: Uukrul від Липень 02, 2008, 09:36:22 ДП
А номерок ноты? А то я что-то не нашел, о разных исправлениях ошибок есть... а саму программку где тянуть не находиться...
Ну может убрали. Поищи на ftp у сапов транспорт K900427.XB4  (EILENBERGER    CI Downport 3.Version) - 2003 год.
У себя не нашел - после апгрейда все старые вычистил из transdir. Осталось только в истории импорта
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Липень 07, 2008, 10:34:00 ДП
COMMIT WORK - Однако при массовых вставках не надо использовать эту конструкцию после каждой вставки новой записи. Опять же на надо заливать все и делать один общий COMMIT. Оптимальным обычно является фиксация обновления/вставки через 500-1000 обработанных записей. К сожалению это правило часто не работает с функциями BAPI, которые не являются повторно входимыми, поэтому там ничего не поделаешь, но после каждого вызова функции нужно делать COMMIT. Опять же если можно сделать фиксацию на несколько разных вызовов BAPI, то нужно пользоваться такой возможностью.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Серпень 01, 2008, 11:20:05 ДП
В продолжении темы о COMMIT WORK и BAPI, в общем есть такая функция BAPI_FIXEDASSET_CHANGE - Изменение карточек ОС, написано ничего так, позволяет выполнять COMMIT после обработки нескольких карточек, так вот надо было изменить порядка ~20 000 записей, в программке случайно сбился счетчик и в итоге COMMIT вызвался только после обновления всех записей. К чему это привело, ну во-первых, каждая следующая запись карточки ОС, обновлялась все медленнее и медленнее, так как рос лог транзакции. В общей сумме оно выросло до 400 Мб и тут пришел COMMIT, ну конца этого процесса я не дождался, так как 3 часа висения на этой строчке и было принято решение, а ну его нафиг. В общем подрихтовали программку, COMMIT через 200 записей и в итоге ~20 000 карточек проскочило минут за 40.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Серпень 06, 2008, 12:08:54 ПП
И еще в продолжении COMMIT WORK-а, в общем при массовой обработке объектов базы или проводке документов возникает иногда ситуация, что нужно или подождать пока объект станет доступен для последующей обработки или пока документ появится в базе данных. Делать задержку в секундах после каждого COMMIT-а, не только не гуманно, но и желательно отрывать руки за такой код, так как один документ + задержка в секунду, это еще куда не шло, но 500 000 объектов + 1 секудна, это месяц работы программы, хотя без этой задержки, записи к примеру льются со скоростью 15-20 объектов в секунду. Поэтому как общая рекомендация после обновления для проверки существования объекта использовать или объекты блокирования объекта или модули чтения таблицы блокировок из примера: http://sapforum.biz/index.php/topic,243.0.html, Во втором случае, проверяем есть ли наш объект в записях блокирования и если есть то ждем, если нет, тогда можем считать что объект уже прошел все обновления и существует в базе данных. А вот для использования объектов блокирования, сначала нужно посмотреть какой объект используется. Например возьмем карточки ОС. Самое просто это зайти в изменения любой карточки ОС, а после этого в другом окне запустить транзакцию SM12. Если у вас больше ничего в других окнах не открыто, то скорее всего там будет одна запись блокирования. Делаете двойной клик на этой записи и получаете детальную информацию по объекту блокирования, рисунок SM12V.png. Нас интересует объект выделенный рамкой, это и есть объект блокировки. Теперь нужно пойти в транзакцию SE11, чтобы узнать функциональные модули управления блокировкой. Вводим полученный объект блокирования, как на рисунке SE11-1.png, жмем просмотр объекта и попадаем в экран просмотра SE11-2.png и там по меню "Перейти к" - "Модули блокировки" и получаем две функции, одна для блокирования объекта основное средство, а другая для деблокирования. Ну а дальше дело техники. После вызова функции создания/обновления карточки ОС, если параметр BAPIRET2 не содержит ошибок, т.е. например создание карточки прошло успешно, то далее вставляем такой код:

CALL FUNCTION 'ENQUEUE_EANLA'
     EXPORTING
          bukrs          = l_bukrs
          anln1          = l_anln1
          anln2          = l_anln2
          _wait          = 'X'
     EXCEPTIONS
          foreign_lock   = 1
          system_failure = 2
          OTHERS         = 3.
IF sy-subrc = 0.
* Запись находится в БД, блокировку можно снять и бежать дальше
  CALL FUNCTION 'DEQUEUE_EANLA'
       EXPORTING
            bukrs = l_bukrs
            anln1 = l_anln2
            anln2 = l_anln3.
ENDIF.

Т.е. система будет пытаться поставить блокировку на созданный/изменный объект, если блокировка установилась, то мы ее тут же снимаем и идем обрабатывать следующие данные, так как запись точно уже существует в БД.
Назва: Re: Оптимизация ABAP-а
Відправлено: bdmalex від Серпень 21, 2008, 05:11:40 ПП
Цитата: Uukrul від Липень 02, 2008, 09:36:22 ДП
А номерок ноты? А то я что-то не нашел, о разных исправлениях ошибок есть... а саму программку где тянуть не находиться...

У меня нет 4.x....Но в блокноте записан номер ноты: 543359 (https://websmp230.sap-ag.de/sap(bD1ydSZjPTAwMQ==)/bc/bsp/spn/sapnotes/index2.htm?numm=543359) ...подходит ??
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Серпень 21, 2008, 05:35:33 ПП
Цитата: bdmalex від Серпень 21, 2008, 05:11:40 ПП
...подходит ??
Подходит конечно  ;)
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Жовтень 09, 2008, 10:25:00 ПП
Не совсем может и оптимизация, но точно про ABAP будет  ;)

Сегодня тут протормозил при вставке записей в свою Z-таблицу. Короче в таблице уже есть некоторое количество данных. Вставляю программно еще парочку, первая запись вставляется, вторая нет, потом еще пара других без проблем заливаются в таблицу. Вставку делаю оператором MODIFY <tab_name>, в цикле. Тупо не мог понять почему оно не отрабатывает, при этом код ошибки 4 (вставка дублирующей записи и это при MODIFY). Короче оказалось что то ли рука дрогнула вчера поздно уже было, то ли еще чего, но вместо просто дополнительного индекса, почему-то создал уникальный индекс. На несчастье, по полю уникального индекса, как раз данные были уникальные и этот индекс создался в тот момент без вопросов,, а я как-то не обратил внимание. Короче проблемы начались утром следующего дня ::) Однако, потребовался перекур и тупо смотрение в код, с мыслью то ли лыжи не едут, то ли снега просто еще нет.
Назва: Re: Оптимизация ABAP-а (Хинты)
Відправлено: Uukrul від Жовтень 23, 2008, 10:40:26 ДП
В общем-то иногда нужно в запросе сказать какой индекс использовать при запросе из базы данных. Админы конечно этого сильно не любят, типа оптимизатор должен сам решать как делать выборку +  админ если что сам порулит этим процессом, а вот при жесткой привязке индекса этого уже не сделаешь. В общем на усмотрение разработчика. Пример для оракловой базы. Будет использоваться индекс "T".

   SELECT * UP TO 10 ROWS FROM mara
                          WHERE MTART = 'HAWA' AND
                                MATKL = '100'
                          %_HINTS ORACLE 'index(mara"T")'.
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Листопад 13, 2008, 07:18:15 ПП
По поводу вложенных запросов.
  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 ).


Известно, что при больших объемах данных, вложенные запросы существенно замедляют быстродействие основного. В приведенной выше выборке вложенный запрос отсекает сторнированные позиции д-тов движений материалов. При большом числе выбираемых позиций (>1000000) данная конструкция в плане быстродействия оказалась более предпочтительней, чем обычный запрос, с последующим отсечением сторно в цикле по полученным записям. Поскольку в позции прямого документа в таблице MSEG нет ссылки на сторнирующий, то в цикле по lt_mseg исключение сторно приходится делать единичной выборкой из MSEG (SELECT SINGLE ...) и при положительном ее результате (sy-subrc = 0) - удаление позиции из вн. таблицы. Единичная выборка в цикле (даже по ключу) и переиндексация lt_mseg при удалении из нее записи оказались неприемлемыми (дамп по таймауту). Вот такой вот частный случай.     
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Листопад 14, 2008, 12:06:09 ПП
Использование вспомогательных вн. таблиц с оператором READ ... BINARY SEARCH.
Необходимое и достаточное условие: устраивающий объем оперативной памяти, выделенной пользователю на сервере приложений (отсутствие дампа по переполнению).
В приведенном выше посте мы получили вн. таблицу lt_mseg с позициями д-тов движений материалов. Как оптимальнее добавить краткие наименования ЕИ материала (в эту же или итоговую таблицу)? Перед основным запросом делаем ряд доп. выборок, в нашем случае, например:
* Единицы измерения
  SELECT mara~matnr t006a~mseh3 INTO TABLE gt_meins FROM mara
                       JOIN t006a ON mara~meins = t006a~msehi
                                  WHERE mara~matnr IN s_matnr
                    AND t006a~spras = sy-langu ORDER BY mara~matnr.

Затем, в цикле по lt_mseg вместо SELECT SINGLE ... мы пользуемся оператором READ TABLE gt_meins WITH KEY matnr = <fs_mseg>-matnr BINARY SEARCH (используется LOOP AT lt_mseg ASSIGNING <fs_mseg>). Т.о. быстродействие цикла можно увеличить на 10-15%, поскольку в течение несколькомиллионных итераций мы обращаемся не к серверу БД, а уже исключительно к серверу приложений.
Примечание: для корректной работы BINARY SEARCH вн. таблица (в нашем случае - gt_meins) должна быть отсортирована по ключу, который используем в операторе READ (см. help).   
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Листопад 14, 2008, 12:31:11 ПП
В догонку к примечаниям: перед оператором READ ... в том же цикле по lt_mseg ЕИ и количества материалов были трансформированы в "стандартные" (из пачек в "ШТ." в данном случае) посредством соотв. ФМ.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Листопад 15, 2008, 08:57:49 ПП
Цитата: Dmitriy від Листопад 14, 2008, 12:31:11 ПП
В догонку к примечаниям: перед оператором READ ... в том же цикле по lt_mseg ЕИ и количества материалов были трансформированы в "стандартные" (из пачек в "ШТ." в данном случае) посредством соотв. ФМ.
Соответствующий ФМ описан тут: http://sapforum.biz/index.php/topic,108.0.html  ;)
Назва: Re: Оптимизация ABAP-а
Відправлено: NachDenken від Грудень 08, 2008, 02:49:37 ПП
Есть большое сомнение, что 2 выборка по mseg в таком виде будет работать быстро, недавно как раз был случай, что такая именно конструкция работала _очень_ медленно, не смотря на то, что и индекс по сторно был, и выборка шла по номеру документа+год материала (по ключу),
спасло: дополнительные условия на mseg поля ebeln ebelp
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Грудень 08, 2008, 03:03:09 ПП
Цитата: NachDenken від Грудень 08, 2008, 02:49:37 ПП
Есть большое сомнение, что 2 выборка по mseg в таком виде будет работать быстро, недавно как раз был случай, что такая именно конструкция работала _очень_ медленно, не смотря на то, что и индекс по сторно был, и выборка шла по номеру документа+год материала (по ключу),
спасло: дополнительные условия на mseg поля ebeln ebelp
Не вопрос, замеры нам помогут. Нет под рукой системы! :(
Ну на более, чем миллион записей выборка "сыграла".
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Грудень 08, 2008, 03:16:23 ПП
Цитата: NachDenken від Грудень 08, 2008, 02:49:37 ПП
Есть большое сомнение, что 2 выборка по mseg в таком виде будет работать быстро, недавно как раз был случай, что такая именно
Это имелось в виду конструкция с:
AND NOT EXISTS ( SELECT * FROM *mseg WHERE smbln = mseg~mblnr
                                             AND sjahr = mseg~mjahr
                                             AND smblp = mseg~zeile ).
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Грудень 08, 2008, 03:18:28 ПП
Да, похоже именно эта. MKPF join MSEG вообще темная тема, индексы нужно делать, иначе...
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Грудень 08, 2008, 03:26:05 ПП
Цитата: Dmitriy від Грудень 08, 2008, 03:18:28 ПП
Да, похоже именно эта. MKPF join MSEG вообще темная тема, индексы нужно делать, иначе...
Ну например можно ораклово (ну если там оракл) таблицу вынести на отдельный раздел, на отдельном диске... и уже это добавит производительности в выборке. А вообще подселекты, вещь тоже темная и как их оптимизатор разрулит, нужно смотреть в каждом отдельном случае.
Назва: Re: Оптимизация ABAP-а
Відправлено: NachDenken від Грудень 08, 2008, 05:10:06 ПП
в пред случае имелось в виду двойная выборка по mseg, про оптимизацию верно, каждый своим опытным путем.
вот тут недавно было, про то, что сначало сделать выборку (select) а потом по внут таблице Read table ...binary , сама сортировать по ключам нужно, а это иногда тоже время требует, если данных много.
вот и призадумаешься, может лучше все таки _дернуть_ из базы select single по ключам чем read table
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Грудень 08, 2008, 05:34:23 ПП
Цитата: NachDenken від Грудень 08, 2008, 05:10:06 ПП
вот и призадумаешься, может лучше все таки _дернуть_ из базы select single по ключам чем read table
Ну тут в каждом случае надо смотреть отдельно... если памяти хватает, то врядли READ SINGLE будет быстрее, хотя конечно если там одно и тоже читается, т.е. например для 100 записей реально будет только 10 различных чтений данных, тогда скорее всего что данные при SELECT будут браться из кэша, что возможно будет быстрее чем выборка с последующей сотрировкой... короче в каждом случае надо смотреть на данные и сервер на котором все это работает.
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Грудень 09, 2008, 03:57:26 ДП
Да и вообще, всего не предугадаешь и всего знать невозможно, оно же по крупицам собирается, с опытом приходит. Мой добрый совет: если это возможно, то лучше прийти к базисникам, познакомиться/поговорить с мужиками, глядишь и помогут, главное не стесняться. ;) Было много случаев, например, когда "перепахивали" систему, вычислили проги, которые пару раз запустили за год, и все... Базис просто инфу дал, когда попросили. С теми же индексами... (с): Опыт сын ошибок трудных. :)     
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Грудень 09, 2008, 04:07:41 ДП
Цитата: NachDenken від Грудень 08, 2008, 02:49:37 ПП
Есть большое сомнение, что 2 выборка по mseg в таком виде будет работать быстро, недавно как раз был случай, что такая именно конструкция работала _очень_ медленно, не смотря на то, что и индекс по сторно был, и выборка шла по номеру документа+год материала (по ключу),
спасло: дополнительные условия на mseg поля ebeln ebelp
У меня вообще долго крутился отчет, самый "энергоемкий" был, т.к. начальству хотелось "всю информацию" сначала в общем виде, а потом с детализацией в гриде. Миллионы записей - это что-то))) А со сторно разрулилось по-другому: разнесли по видам движений. На использовании упомянутой мной конструкции не настаиваю, но реально замеры показали, что она в моем случае работала быстрее. Хотя тут больше скажут MM-щики, я таки ABAP-ер и насколько понимаю, часть видов движений стандартна, но можно свои настроить. ;)  
Назва: Использование внутренних таблиц типа SORTED
Відправлено: Dmitriy від Січень 13, 2009, 03:29:33 ПП
*&---------------------------------------------------------------------*
*& Report  YXXX
*&---------------------------------------------------------------------*
*& Данный отчет - тестовый, для отладки всевозможных ситуаций
*&---------------------------------------------------------------------*
REPORT yxxx.
* Для заголовков
TYPES: BEGIN OF t1,
  bukrs TYPE bukrs,
  belnr TYPE belnr_d,
  gjahr TYPE gjahr,
* Здесь еще какие-нибудь наши поля
* ................,
  END OF t1.
* Для позиций
TYPES: BEGIN OF t2,
  bukrs TYPE bukrs,
  belnr TYPE belnr_d,
  gjahr TYPE gjahr,
  buzei TYPE buzei,
  buzid TYPE buzid,
* Здесь еще какие-нибудь наши поля
* ................,
  sgtxt TYPE sgtxt,
  END OF t2.
* Таб. заг., ее в нашем случае можно было бы объявить произвольно
DATA: gt_h TYPE SORTED TABLE OF t1
      WITH UNIQUE KEY bukrs belnr gjahr. " Заголовки
* Таб. позиций, объявляем именно так
DATA: gt_p TYPE SORTED TABLE OF t2
      WITH UNIQUE KEY bukrs belnr gjahr buzei. " Позиции
* Рабочую область таблицы позиций объявляем так для иллюстрации примера
* классического использования оператора ASSIGN, можно найти в примерах:
* SE80-)>Среда-)>Примеры-)>Примеры производительности-)>Internal tables
* -)>Using the Assigning Comand. Для таблицы заголовков можно было бы
* обойтись обычной Work area:
* DATA: gs_h LIKE LINE OF gt_h.
FIELD-SYMBOLS: <gs_h> LIKE LINE OF gt_h,
               <gs_p> LIKE LINE OF gt_p.
*&---------------------------------------------------------------------*
START-OF-SELECTION.

  PERFORM selection. " Выбор данных

  PERFORM processing. " Обработка данных

END-OF-SELECTION.

* Далее - процедура изменения FI-документов в БД

*&---------------------------------------------------------------------*
*&      Form  SELECTION
*&---------------------------------------------------------------------*
FORM selection.
* Выбор из БД
ENDFORM.                    " SELECTION
*&---------------------------------------------------------------------*
*&      Form  PROCESSING
*&---------------------------------------------------------------------*
FORM processing.

  LOOP AT gt_h INTO <gs_h>.
* { Здесь какая-либо обработка
* ..........................
* Конец обработки }
    LOOP AT gt_p ASSIGNING <gs_p> WHERE bukrs = <gs_h>-bukrs
                                                      AND belnr = <gs_h>-belnr
                                                      AND gjahr = <gs_h>-gjahr.
* { Здесь какая-либо обработка
* ..........................
* Конец обработки }
      IF <gs_p>-buzid NE space. " Позиция контрагента
* Замена текста позиции (MODIFY строки вн.табл.)
        <gs_p>-sgtxt = 'Добавлено из старой системы'.
      ENDIF.
    ENDLOOP.
  ENDLOOP.

ENDFORM.                    " PROCESSING

В данном случае, при использовании вложенного цикла, происходит уменьшение числа итераций засчет соответствующего объявления вн. таблицы позиций. В противном случае, не смотря на условие WHERE, происходит полный перебор всех записей таблицы gt_p.
Назва: Re: Оптимизация ABAP-а (Грабли с SELECT)
Відправлено: Uukrul від Січень 22, 2009, 10:41:06 ПП
В общем не совсем оптимизация, но скажем так грабли с небольшой ручкой, проявились на системе 4.6 операционка HP-UX версии 11.31, база Oracle версия 10.хх с хвостиком, на системе где Oracle 9.xx с хвостиком такого эффекта не наблюдалось, так что скорее всего это похоже грабли от оракловой базы. И так что и как было.

1. Есть своя Z-табличка, есть свои программки, которые туда чего-то пишут, а другие чего-то читают. В какой-то момент надо было добавить поле, тип поля NUMC. Добавил поле, к примеру R_FILE TYPE MY_DATA, где в словаре определено как MY_DATA(5) TYPE n. Ясное дело таблицу переактивировал, через утилиту базы данных сделал адаптацию с сохранением значений.
2. Написал программку, которая для некоторых записей из таблички заполнила новое поле R_FILE нужными значениями.
3. Перенес все это дело в продуктивную систему, там тоже для части полей заполнил данные в новое поле.

А вот дальше началось интересное, запрос вида:
SELECT * INTO lt_my_table FROM my_table
WHERE R_FILE = space.
На выходе получаю SY-SUBRC = 4.
==========
SELECT * INTO lt_my_table FROM my_table
WHERE R_FILE = 0.
На выходе получаю SY-SUBRC = 4.
==========
SELECT * INTO lt_my_table FROM my_table
WHERE R_FILE = '0'.
На выходе получаю SY-SUBRC = 4.
==========
SELECT * INTO lt_my_table FROM my_table
WHERE R_FILE = '00000'.
На выходе получаю SY-SUBRC = 4.

Короче, выбрать пустые записи, которые просто запросом SELECT * INTO lt_my_table FROM my_table выбираются кучей и при просмотре показываются как '0' или как '00000', выбрать никак не получается при прямом указании значения, хотя теоретически по равно space, должно было бы выбраться. При этом если сделать:

SELECT * FROM my_table.
  IF my_table-r_file = space.
*  Сюда заходит и именно вот те самые пустые записи типа находятся
*  причем можно было бы написать IF my_table-r_file = '0', и тоже заходит
  ENDIF.
ENDSELECT.

Короче, пришлось сделать вторую программку вида:
SELECT * FROM my_table.
  IF my_table-r_file = space.
    my_table-r_file = '0'.
    MODIFY my_table.
  ENDIF.
ENDSELECT.
COMMIT WORK.

После чего все типа заработало... кстати, самое интересное, что на версии Oracle 9 с хвостиком (система разработки), такого эффекта не наблюдается, ну правда сюда поле не транспортом попало, но в принципе это похоже не важно, так как адаптация таблицы, через утилиту базы данных делалась по аналогии с продуктивом. Причем если записи вставлять после добавления этого нового поля, то такие записи находятся запросом равно space или равно ноль, без проблем.

В общем вот такая вот грабелька попалась, т.е. состояние добавленного поля в таблицу для уже существующих записей для поля типа NUMC (другие не проверял) вообще какое-то не определенное в базе данных, причем после считывания оно корректно конвертируется в space/0 и уже при проверке в IF все корректно, но вот выбрать такие поля SELECT-от ну никак не получается, а ощущения, типа SE16 просмотреть все... вот она запись, ставишь на селекционном экране поле равно пустому значению, а она говорит нет значений для показа и некоторое время чувствуешь себя типа а где это я, а как это я  ???
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Січень 22, 2009, 10:47:58 ПП
а не проходит where r_file is null ?
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Січень 22, 2009, 10:50:04 ПП
 как по мне так правильно выбирать .... хотя сам помню когда-то сидел пытался выбрать по условию что поле типа дата пустое ..... самое интересное, сюда не написал .... а теперь не помню ....
кажись писал WHERE docdate = '' ....
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Січень 22, 2009, 10:50:48 ПП
Цитата: Паганель від Січень 22, 2009, 10:47:58 ПП
а не проходит where r_file is null ?
не пробовал... но тут похоже если так пройдет, то надо будет все запросы по этому полю по всей программе менять на r_file is null or r_file = 0, что уже не кошерно, так что проще таки новое поле принудительно присвоить в space или в ноль, если возможно и потом уже не париться.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Січень 22, 2009, 10:51:52 ПП
Цитата: Паганель від Січень 22, 2009, 10:50:04 ПП
как по мне так правильно выбирать .... хотя сам помню когда-то сидел пытался выбрать по условию что поле типа дата пустое ..... самое интересное, сюда не написал .... а теперь не помню ....
кажись писал WHERE docdate = '' ....
Не с датой там фишка другая, там точно известно что поле дата будет '00000000'.
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Січень 22, 2009, 10:52:40 ПП
ну может быть, я же не знаю твоих условий .....

как по мне закладыватся на то что ты обновил, источник ошибок .... вдруг забудеш обновить и выборка пойдет ....
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Січень 22, 2009, 10:53:33 ПП
Цитата: Uukrul від Січень 22, 2009, 10:51:52 ПП
Не с датой там фишка другая, там точно известно что поле дата будет '00000000'.
буду на работе поищу, там ксати у меня так не прошло ..... не помню точно
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Січень 22, 2009, 10:57:21 ПП
Цитата: Паганель від Січень 22, 2009, 10:52:40 ПП
как по мне закладыватся на то что ты обновил, источник ошибок .... вдруг забудеш обновить и выборка пойдет ....
Условие я написал какое... а обновить, так это надо в любом случае первый раз сделать для всех записей которые существовали до внесения нового поля, для записей, который будут вставлены после добавления нового поля, уже корректно работает выборка на space или ноль. Так что тут именно грабли в том что поле не конвертировано. Возможно что IS NULL пройдет, но если у меня запросов уже три десятка по программе, то добавлять лишнее сравнение на то что пока обработаются все старые записи, да и вообще лишнее сравнение, которое через месяц точно уже будет лишним, короче апдейтик будет самое оно.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Лютий 19, 2009, 09:12:57 ПП
В общем из этого поста: http://sapforum.biz/index.php/topic,510.0.html

Есть выборка и есть обработка/модификация данных внутренней таблицы в LOOP AT / ENDLOOP. Само собой есть два варианта, через MODIFY и используя FIELD-SYMBOLS, в общем во втором случае производительность просто в разы больше, что видно из теста! Так что считайте, что это рекомендации лучших собаководов при обновлении внутренних таблиц данных.

Однако подтверждаю, и так провел небольшой тест, есть табличка MSEG, система тестовая записей  123 226, сделана программка следующего вида:

REPORT  yuuk_test_select.

DATA: lt_mseg LIKE mseg OCCURS 1 WITH HEADER LINE,
      runtime_1 TYPE i,
      runtime_2 TYPE i,
      time_diff TYPE i.

FIELD-SYMBOLS: <fs> LIKE LINE OF lt_mseg.

SELECT * INTO TABLE lt_mseg
FROM mseg.

GET RUN TIME FIELD runtime_1.
LOOP AT lt_mseg.
  lt_mseg-bwart = '000'.
  MODIFY lt_mseg.
ENDLOOP.
GET RUN TIME FIELD runtime_2.
time_diff = runtime_2 - runtime_1.
WRITE: / time_diff.

GET RUN TIME FIELD runtime_1.
LOOP AT lt_mseg ASSIGNING <fs>.
  <fs>-bwart = '000'.
ENDLOOP.
GET RUN TIME FIELD runtime_2.
time_diff = runtime_2 - runtime_1.
WRITE: / time_diff.

Результат на экране, комментарии я так думаю излишние, разница в производительности даже не на лице  ;) в надцать раз практически, т.е.  192 580 миллисекунд против  12 172, кажется закрывают данный вопрос как нужно делать обновления внутренних таблиц.
Назва: Re: Оптимизация ABAP-а
Відправлено: NachDenken від Травень 21, 2009, 09:06:14 ДП
Спасибо партии администрации за возвращения ника :)
есть вопрос скорее по оптимизации выполнения select
задачка выполнить 2-3 тяжелых селекта в паралельном фоновом режиме,
есть 2 (у меня) варианта
1) call function селект ...new task и потом их ловить в процедурке on end task
2) запустить  job_open submit селект

как лучше ?

селект к одной и тойже таблице в 2 разных фоновых заданиях будет быстрее чем 2 селекта последовательно ?
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Травень 21, 2009, 09:37:30 ДП
Цитата: NachDenken від Травень 21, 2009, 09:06:14 ДП
1) call function селект ...new task и потом их ловить в процедурке on end task
2) запустить  job_open submit селект
Я не тестировал оба варианта, делал по второму пункту.

Цитата: NachDenken від Травень 21, 2009, 09:06:14 ДП
селект к одной и тойже таблице в 2 разных фоновых заданиях будет быстрее чем 2 селекта последовательно ?
Быстрее будет работать два параллельных запроса, чем два последовательных, но само собой каждый отдельный запрос будет медленнее при параллельной обработке чем при последовательно.

Тут есть правда такая вещь как кеширование, если данные обоих запросов очень близкие по теме, то... я бы замерил время выполнения обоих вариантов на твоих данных и тода уже принимал бы решение. (Как измерять время выполнения тут уже написано)
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Червень 05, 2009, 02:28:41 ПП
Можно и мои 5 коп?

По поводу "LOOP AT + INTO" vs "LOOP AT + ASSIGNING", тут как раз занимаюсь оптимизацией одной гениальной програмульки, написанной неким месье Паганелем (дизайн и все ..... лапочка, только быстродействие).....Ннндда, .....

вот пару замерчиков, выводы очевидны:
1. LOOP AT gt_alvtab INTO ls_alvtab.
2. LOOP AT gt_alvtab ASSIGNING <fs_alvtab>.
Назва: Re: Оптимизация ABAP-а
Відправлено: NachDenken від Червень 05, 2009, 02:31:38 ПП
ого какая существенная разница в тормозах ,
для LOOP AT gt_alvtab ASSIGNING <fs_alvtab>.
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Червень 05, 2009, 02:35:53 ПП
Цитата: NachDenken від Червень 05, 2009, 02:31:38 ПП
ого какая существенная разница в тормозах ,
для LOOP AT gt_alvtab ASSIGNING <fs_alvtab>.

Ссори, привел полные логи, но реально изменения касались только последней строки
calc_data 14.457.162 и calc_data 11.666.928

P.S. В пред. посте рисунки поменял :-)
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Червень 05, 2009, 02:44:01 ПП
Еще пару заметок и мыслей-вопросов

1. Странно SAP выбирает какие индексы использовать, раньше я думал что порядок
полей в условии WHERE, как раз и определяет, какой индекс юзается, как оказалось -  не так.
На выбор индекса, как я понял, влияют только количество параметров в условии WHERE.

2. ! Как оказалось, если параметр (selopt) не заполнен, он все равно влияет на выбор индекса.
Т.е.:
Первый вариант:
 WHERE
         matnr IN  so_matnr     AND
         werks IN  so_werks     AND
         sobkz = 'K'            AND          
         lifnr IN  so_lifnr     AND " даже если пустой so_lifnr, он все равно влияет на выбор индекса

У меня из-за него подтягивался какой-то "неправильный" :-) индекс.

Второй вариант:
WHERE
         matnr IN  so_matnr     AND
         werks IN  so_werks     AND
         sobkz = 'K'            AND          
         "!!!!! lifnr IN  so_lifnr     AND " закомментировал, теперь выбирается нужный индекс...


уфффф.... сссори, что сумбурно, радость переполняет ...
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Червень 05, 2009, 04:07:39 ПП
Цитата: Паганель від Червень 05, 2009, 02:44:01 ПП
На выбор индекса, как я понял, влияют только количество параметров в условии WHERE.
Ну ты же сам написал... порядок полей в условии WHERE!!!, а какая разница есть справа значение для сравнения или нет?!
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Червень 05, 2009, 04:49:22 ПП
Цитата: Uukrul від Червень 05, 2009, 04:07:39 ПП
Ну ты же сам написал... порядок полей в условии WHERE!!!, а какая разница есть справа значение для сравнения или нет?!
Ну вот, хотя если реально в данный момент времени, данные не передаются, оптимизатор должен бы отбросить несипользуемые  условия ....
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Червень 05, 2009, 04:57:38 ПП
Цитата: Паганель від Червень 05, 2009, 04:49:22 ПП
Ну вот, хотя если реально в данный момент времени, данные не передаются, оптимизатор должен бы отбросить несипользуемые  условия ....
Ну я бы про отбросить так не говорил, так как я как раз иногда использую такую конструкцию чтобы выбирался нужный мне индекс при выборке, а вообще у тебя оракловая база? Прибей индекс гвоздями и буде тебе счастье...
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Червень 05, 2009, 05:00:37 ПП
Цитата: Uukrul від Червень 05, 2009, 04:57:38 ПП
Ну я бы про отбросить так не говорил, так как я как раз иногда использую такую конструкцию чтобы выбирался нужный мне индекс при выборке, а вообще у тебя оракловая база? Прибей индекс гвоздями и буде тебе счастье...
да нет "ДИБИ Цвай" ....  :-), это как "гвоздями"?
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Червень 05, 2009, 05:04:31 ПП
Цитата: Паганель від Червень 05, 2009, 05:00:37 ПП
да нет "ДИБИ Цвай" ....  :-), это как "гвоздями"?
Ну под DB2 не знаю надо документацию смотреть, опять же может Дмитрий знает, там типа хинт использования индекса можно указывать... но админы БД обычно это сильно не любят... т.е. мы жестко говорим какой индекс должна использовать система.
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Червень 05, 2009, 05:11:27 ПП
Цитатауфффф.... сссори, что сумбурно, радость переполняет ...
По праву передавшего эстафетную палочку месье Паганелю. ;)
2 Паганель: как-то внятно писать сразу нужно писать, задача, результат, выводы, стройность текста сообщения должна быть на уровне. А то как же месье Паганель, вы модератором тематики в скором времени будете: начинающий не поймет о чем это он, куда плыть? ::)

P.S. Это так, оффтоп, просто контент должен быть четким. 8)
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Червень 05, 2009, 05:12:41 ПП
Цитата: Uukrul від Червень 05, 2009, 05:04:31 ПП
Ну под DB2 не знаю надо документацию смотреть, опять же может Дмитрий знает, там типа хинт использования индекса можно указывать... но админы БД обычно это сильно не любят... т.е. мы жестко говорим какой индекс должна использовать система.
Хинт иногда нужно указывать, однозначно.
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Червень 05, 2009, 05:15:22 ПП
Цитата: Dmitriy від Червень 05, 2009, 05:11:27 ПП
По праву передавшего эстафетную палочку месье Паганелю. ;)
2 Паганель: как-то внятно писать сразу нужно писать, задача, результат, выводы, стройность текста сообщения должна быть на уровне. А то как же месье Паганель, вы модератором тематики в скором времени будете: начинающий не поймет о чем это он, куда плыть? ::)
Все правильно Вы написали, мой уважаемый друг Дима, только не учли одного: природы человека по имени Паганель ......  который и получил сие прозвище еще в школе, за сию рассеянность и непоследовательность ...  ссори ... стараюсь.... буду исправляется ..
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Червень 05, 2009, 05:15:56 ПП
Цитата: Dmitriy від Червень 05, 2009, 05:12:41 ПП
Хинт иногда нужно указывать, однозначно.
Слышал, вроде бы видел, тока не помню как пишется ....  ;-)
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Червень 05, 2009, 05:21:12 ПП
Цитата: Dmitriy від Червень 05, 2009, 05:11:27 ПП
По праву передавшего эстафетную палочку месье Паганелю. ;)
P.S. Это так, оффтоп, просто контент должен быть четким. 8)

Поддежрживаю, "должен быть четким".

Цитата: Dmitriy від Червень 05, 2009, 05:11:27 ПП
..... вы модератором тематики в скором времени будете:.....
Ну это бабка на двое сказала, как говортся "ры...м еще не дорос"
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Червень 05, 2009, 05:23:09 ПП
Цитата: Dmitriy від Червень 05, 2009, 05:12:41 ПП
Хинт иногда нужно указывать, однозначно.
Синтаксис не подскажешь сразу, а то я что-то найти не могу..
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Червень 05, 2009, 05:30:06 ПП
Цитата: Uukrul від Червень 05, 2009, 05:23:09 ПП
Синтаксис не подскажешь сразу, а то я что-то найти не могу..
ага, а то видел, кажись в mb5b... сижу, ищу ...  :-(
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Червень 05, 2009, 08:57:06 ПП
Цитата: Паганель від Червень 05, 2009, 05:21:12 ПП
Поддежрживаю, "должен быть четким".
Ну это бабка на двое сказала, как говортся "ры...м еще не дорос"
Еще раз поддерживаю, "дурак, это тот кого никто не понимает"
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Червень 05, 2009, 10:18:09 ПП
Цитата: Uukrul від Червень 05, 2009, 05:23:09 ПП
Синтаксис не подскажешь сразу, а то я что-то найти не могу..
Нет, к сожелению, этот код не "засолил", повезло в свое время по поводу мегаотчетов, но может мужики-абаперы подскажут что, залез в исходники - много их... Нормально просто всегда индексы работали, а еще и с базисом общался, грамотный базисник дюжины начинающих абаперов стоит, если не вредный. ;) А потом уже (по поводу больших отчетов), мы просто присаживались с консулами (когда они были!) и предметно общаясь, договаривались, что они, как постановщики, будут клиенту говорить, можно/нельзя, а то иногда такие казусы... ::) Пошукаю, если найду - отпишу.
 
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Червень 05, 2009, 10:24:52 ПП
Цитата: Dmitriy від Червень 05, 2009, 10:18:09 ПП
А потом уже (по поводу больших отчетов), мы просто присаживались с консулами (когда они были!) и предметно общаясь, договаривались, что они, как постановщики, будут клиенту говорить, можно/нельзя, а то иногда такие казусы... ::) Пошукаю, если найду - отпишу.
Хорошо, наверное тебе, Дима, просто, нет у меня консулов, «Аз есмь...», и косул, и абапер, в одном лице :-), и задачу ставят не в виде ТЗ, а ближе к ФД (функциональному требованию, общему описанию, как должно быть) ... ну как говорят "и кузнец, и жнец, и трубе дудец"....
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Червень 05, 2009, 10:29:12 ПП
Цитата: Паганель від Червень 05, 2009, 10:24:52 ПП
Хорошо, наверное тебе, Дима, просто, нет у меня консулов, «Аз есмь...», и косул, и абапер, в одном лице :-), и задачу ставят не в виде ТЗ, а ближе к ФД (функциональному требованию, общему описанию, как должно быть) ... ну как говорят "и кузнец, и жнец, и трубе дудец"....
Да это понятно, просто когда опыта поднаберешь, сможешь авторитетом "давить". А то мечтателей много, дай им то, это, а SAP ведь тоже не резиновый. :D
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Червень 05, 2009, 10:31:33 ПП
Цитата: Dmitriy від Червень 05, 2009, 10:29:12 ПП
Да это понятно, просто когда опыта поднаберешь, сможешь авторитетом "давить". А то мечтателей много, дай им то, это, а SAP ведь тоже не резиновый. :D
Знаем"с мы таких "мечтателей", сами такие, как сделаем, потом еще недельку оптимизируем .....

Дима, а ты о чем?
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Червень 05, 2009, 10:53:06 ПП
Цитата: Паганель від Червень 05, 2009, 10:31:33 ПП
Знаем"с мы таких "мечтателей", сами такие, как сделаем, потом еще недельку оптимизируем .....

Дима, а ты о чем?
О понимании бизнес-процессов компании самим, руководством оной и умением объяснить Клиенту, не то, что он не прав, а то, как надо, т.е. научить/объяснить и подвести к тому, чтобы он был прав, но с учетом специфики параметров "железа" на котором все это дело функционирует и системных настроек.
Назва: Re: Оптимизация ABAP-а
Відправлено: NachDenken від Червень 10, 2009, 11:26:06 ДП
не могу найти пост где месье Паганель рассказывал про зависимость условий where и выбор индекса
действительно ли это так
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Червень 10, 2009, 11:28:39 ДП
Цитата: NachDenken від Червень 10, 2009, 11:26:06 ДП
не могу найти пост где месье Паганель рассказывал про зависимость условий where и выбор индекса
действительно ли это так
страницей выше в этой же теме (только это вопрос спорный)
http://sapforum.biz/index.php/topic,174.msg4061.html#msg4061 (http://sapforum.biz/index.php/topic,174.msg4061.html#msg4061)
Назва: Re: Оптимизация ABAP-а
Відправлено: NachDenken від Червень 11, 2009, 01:24:28 ПП
еще нужен синтаксис хинта ?
%_HINTS ORACLE 'index(MKPF "MKPF~Zblabla")'.
Назва: Re: Оптимизация ABAP-а
Відправлено: NachDenken від Червень 11, 2009, 01:26:03 ПП
по поводу индекса,
думаю со стратегией выбора индекса в sap не все так просто,
1 и тот же селект и условия, при одинаковых индексах в разных мандантах выбор разный.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Червень 11, 2009, 01:59:34 ПП
Цитата: NachDenken від Червень 11, 2009, 01:26:03 ПП
1 и тот же селект и условия, при одинаковых индексах в разных мандантах выбор разный.
Ну там еще статистика индекса смотрится... т.е. для теста желательно сбор статистики сделать в обоих системах, посмотреть на результат, ну если данные в системах одинаковые, то должно совпасть и уже потом запускать отчеты и смотреть на индексы.
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Червень 17, 2009, 03:37:07 ПП
Тут вот опять делаю оптимизацию, странные результаты:  

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


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

Может это для небольшого к-ва тестовых данных?
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Червень 17, 2009, 03:48:10 ПП
Ошибся, в одном месте не заменил
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.
Назва: Re: Оптимизация ABAP-а
Відправлено: Удав від Червень 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.
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Червень 17, 2009, 09:13:07 ПП
Цитата: Удав від Червень 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.

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

Назва: Re: Оптимизация ABAP-а
Відправлено: NachDenken від Червень 18, 2009, 10:04:00 ДП

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

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

collect мне суммирует p2
Спасибо.
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Червень 18, 2009, 10:09:55 ДП
Цитата: 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 (http://sapforum.biz/index.php/topic,174.msg726.html#msg726)

Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Червень 18, 2009, 10:52:09 ДП
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.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Червень 18, 2009, 11:15:41 ДП
Цитата: NachDenken від Червень 18, 2009, 10:04:00 ДП
collect мне суммирует p2
Ну таки да... руками через LOOP AT ENDLOOP. разве что... я что-то никаких описаний типа отключения суммирования для цифровых полей не нашел  ::)
Назва: Re: Оптимизация ABAP-а
Відправлено: NachDenken від Червень 24, 2009, 11:20:12 ДП
помните ?
1) call function селект ...new task и потом их ловить в процедурке on end task
2) запустить  job_open submit селект

1 пункт не фоновый получается, а просто параллельный
2) и фоновый и паралельный
Назва: Re: Оптимизация ABAP-а
Відправлено: Удав від Липень 27, 2009, 08:34:12 ПП
Цитата: Паганель від Червень 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 или достигнут конец таблицы - выход из цикла.
Назва: Re: Оптимизация ABAP-а
Відправлено: Martha від Липень 29, 2009, 11:52:49 ДП
Цитата: Uukrul  link=topic=174.msg4062#msg4062 date=1244207259
Ну ты же сам написал... порядок полей в условии WHERE!!!, а какая разница есть справа значение для сравнения или нет?!

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

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



Это вопрос?

Если да, то порядок не знаю, но наличие полей и значений - да.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Липень 29, 2009, 12:27:37 ПП
Цитата: Martha від Липень 29, 2009, 11:52:49 ДП
этот порядок полей должен соответствовать порядку следования полей в индексе
Причем в индексе если таблица мандантно-зависимая, то обязательно должно быть включено поле манданта. Или иначе надо в запросе явно указывать что мандант не использовать.
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Липень 29, 2009, 12:35:09 ПП
Цитата: Uukrul  link=topic=174.msg4566#msg4566 date=1248859657
Причем в индексе если таблица мандантно-зависимая, то обязательно должно быть включено поле манданта. Или иначе надо в запросе явно указывать что мандант не использовать.

Пример, или подробнее можно?
Назва: Re: Оптимизация ABAP-а
Відправлено: Martha від Липень 30, 2009, 01:33:42 ПП
Цитата: Паганель від Липень 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, если в индексе они идут – см выше.
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Липень 30, 2009, 01:44:37 ПП
Цитата: Martha від Липень 30, 2009, 01:33:42 ПП
У нас есть таблица  t1 в которой помимо ключа, есть индекс по полям f1, f3,f6, f7.

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

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


По моим наблюдениям (т.е. это ИМХО), разницы нет, порядок и количество влияет только на выбор индекса, т.е. если у вас есть два индекса с полями f1, f2, f3 и f1,f3 то выбор идет как раз по порядку следования полей......
Хотя может на это влияет еще и используемая БД......

Кстати вы смотрели какой индекс используется (st05)?

У вас какая то конкретная проблема? Может приведете код и какие у вас индексы?
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Липень 30, 2009, 01:48:38 ПП
Цитата: Паганель від Липень 29, 2009, 12:35:09 ПП
Пример, или подробнее можно?
Ну индекс желательно делать так... как на картинке, первое поле мандантик, так как при запросе
SELECT * FROM EQUI
WHERE MATNR = xxx AND
     SERNR = zzzz AND
     WERK = yyy.

Будет работать индекс, так как на уровень запроса пойдут так же данные манданта.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Липень 30, 2009, 01:49:38 ПП
Цитата: Паганель від Липень 30, 2009, 01:44:37 ПП
Хотя может на это влияет еще и используемая БД......
Ну для оракла порядок важен... если его не соблюдать, то индексы просто не используются в таком случае...
Назва: Re: Оптимизация ABAP-а
Відправлено: Удав від Серпень 05, 2009, 11:39:06 ДП
Цитата: Uukrul  link=topic=174.msg4587#msg4587 date=1248950978
Ну для оракла порядок важен... если его не соблюдать, то индексы просто не используются в таком случае...
Это для какой версии Oracle?
Для 9-ки без разницы, в каком порядке идут поля в WHERE...
Оптимизатор подбирает один из индексов:
-с наибольшим количеством совпадающих с условием полей
-с полями, по которым селективность больше.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Серпень 05, 2009, 11:42:05 ДП
Цитата: Удав від Серпень 05, 2009, 11:39:06 ДП
Это для какой версии Oracle?
Для 9-ки без разницы, в каком порядке идут поля в WHERE...
У нас 10 с копейками, админы настаивают на соблюдении порядка следования индексов... хотя я тоже был уверен что оптимизатор типа умнее должен быть... в противном случае индекс почему-то не подхватывается.
Назва: Re: Оптимизация ABAP-а
Відправлено: Удав від Серпень 05, 2009, 11:49:20 ДП
Вот примеры:
SQL Statement                                                                   
                                                                               
SELECT                                                                         
  *                                                                             
FROM                                                                           
  mseg                                                                         
WHERE                                                                           
  bwart = :A1   and charg = :a2   and werks = :a3                               
                                                                               
Execution Plan                                                                 
                                                                               
SELECT STATEMENT ( Estimated Costs = 1 , Estimated #Rows = 1 )                 
                                                                               
     5  2 TABLE ACCESS BY INDEX ROWID MSEG                                     
          ( Estim. Costs = 1 , Estim. #Rows = 1 )                               
                                                                               
            1 INDEX SKIP SCAN MSEG~ZZ2                                         
              ( Estim. Costs = 3 , Estim. #Rows = 1 )                           
              Search Columns: 3                                                 

NONUNIQUE  Index   MSEG~ZZ2                     
                                                 
Column Name                     #Distinct       
MANDT                                          1
CHARG                                    193 201
WERKS                                         58
BWART                                         63


SELECT                                                                               
  *                                                                                 
FROM                                                                                 
  mseg                                                                               
WHERE                                                                               
  bwart = :A1   and werks = :a3                                                     
                                                                                     
Execution Plan                                                                       
SELECT STATEMENT ( Estimated Costs = 1 916 , Estimated #Rows = 3 700 )             
                                                                                     
     5  2 TABLE ACCESS BY INDEX ROWID MSEG                                           
          ( Estim. Costs = 1 916 , Estim. #Rows = 3 700 )                           
                                                                                     
            1 INDEX SKIP SCAN MSEG~M                                                 
              ( Estim. Costs = 17 536 , Estim. #Rows = 3 700 )                       
              Search Columns: 2           

NONUNIQUE  Index   MSEG~M                       
                                                 
Column Name                     #Distinct       
MANDT                                          1
MATNR                                     17 533
WERKS                                         58
LGORT                                        729
BWART                                         63
SOBKZ                                          3                                           
Назва: Re: Оптимизация ABAP-а
Відправлено: Удав від Серпень 05, 2009, 11:53:44 ДП
А вот что получается при добавлении условия с MANDT ;)
SELECT                                                                            
 *                                                                              
FROM                                                                              
 mseg                                                                            
WHERE                                                                            
 mandt = :A4   and werks = :a3   and bwart = :A1                                
                                                                                 
                                                                                 
Execution Plan                                                                    
SELECT STATEMENT ( Estimated Costs = 228 , Estimated #Rows = 3 700 )            
                                                                                 
    5  2 TABLE ACCESS BY INDEX ROWID MSEG                                        
         ( Estim. Costs = 228 , Estim. #Rows = 3 700 )                          
                                                                                 
           1 INDEX RANGE SCAN MSEG~ZZ5                                          
             ( Estim. Costs = 1 053 , Estim. #Rows = 3 700 )                    
             Search Columns: 3      

SELECT                                                                         
  *                                                                             
FROM                                                                           
  mseg                                                                         
WHERE                                                                           
  mandt = :A4   and bwart = :A1   and werks = :a3                               
                                                                               
                                                                               
Execution Plan                                                                 
SELECT STATEMENT ( Estimated Costs = 228 , Estimated #Rows = 3 700 )           
                                                                               
     5  2 TABLE ACCESS BY INDEX ROWID MSEG                                     
          ( Estim. Costs = 228 , Estim. #Rows = 3 700 )                         
                                                                               
            1 INDEX RANGE SCAN MSEG~ZZ5                                         
              ( Estim. Costs = 1 053 , Estim. #Rows = 3 700 )                   
              Search Columns: 3                                                 

NONUNIQUE  Index   MSEG~ZZ5                    
                                               
Column Name                     #Distinct      
MANDT                                          1
WERKS                                         58
LGORT                                        729
BWART                                         63
SOBKZ                                          3
                                           
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Серпень 05, 2009, 11:54:21 ДП
SELECT                                                                          
 *                                                                            
FROM                                                                            
 mseg                                                                          
WHERE                                                                          
 bwart = :A1   and charg = :a2   and werks = :a3                              

Давай этот запрос со сменой порядка следования полей, т.е. количество полей тоже 3, но порядок разный.
Назва: Re: Оптимизация ABAP-а
Відправлено: Удав від Серпень 05, 2009, 04:33:21 ПП
С мандантом
SQL Statement                                                                 
                                                                               
SELECT                                                                         
  *                                                                           
FROM                                                                           
  mseg                                                                         
WHERE                                                                         
  mandt = :a01   and charg = :a2   and werks = :a3   and bwart = :a4           
                                                                               
Execution Plan                                                                 
SELECT STATEMENT ( Estimated Costs = 1 , Estimated #Rows = 1 )               
                                                                               
     5  2 TABLE ACCESS BY INDEX ROWID MSEG                                     
          ( Estim. Costs = 1 , Estim. #Rows = 1 )                             
                                                                               
            1 INDEX RANGE SCAN MSEG~ZZ2                                       
              ( Estim. Costs = 3 , Estim. #Rows = 1 )                         
              Search Columns: 4                                               

Без манданта
SQL Statement                                                                     
                                                                                 
SELECT                                                                           
  *                                                                               
FROM                                                                             
  mseg                                                                           
WHERE                                                                             
  werks = :a3   and charg = :a2   and bwart = :a4                                 
                                                                                 
Execution Plan                                                                   
SELECT STATEMENT ( Estimated Costs = 1 , Estimated #Rows = 1 )                   
                                                                                 
     5  2 TABLE ACCESS BY INDEX ROWID MSEG                                       
          ( Estim. Costs = 1 , Estim. #Rows = 1 )                                 
                                                                                 
            1 INDEX SKIP SCAN MSEG~ZZ2                                           
              ( Estim. Costs = 3 , Estim. #Rows = 1 )                             
              Search Columns: 3                                                   
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Серпень 05, 2009, 04:38:35 ПП
Ну судя по всему не влияет... надо будет посмотреть у себя. А то может зря поверил на слово админам ::)
Назва: Re: Оптимизация ABAP-а
Відправлено: Martha від Серпень 07, 2009, 08:35:54 ДП
Цитата: Паганель від Липень 30, 2009, 01:44:37 ПП
По моим наблюдениям (т.е. это ИМХО), разницы нет, порядок и количество влияет только на выбор индекса, т.е. если у вас есть два индекса с полями f1, f2, f3 и f1,f3 то выбор идет как раз по порядку следования полей......
Хотя может на это влияет еще и используемая БД......

Кстати вы смотрели какой индекс используется (st05)?

У вас какая то конкретная проблема? Может приведете код и какие у вас индексы?

как посмотреть какие индексы используются? в st05  я вижу только запрос
Назва: Re: Оптимизация ABAP-а
Відправлено: tav_48 від Серпень 07, 2009, 09:42:00 ДП
Цитата: Martha від Серпень 07, 2009, 08:35:54 ДП
как посмотреть какие индексы используются? в st05  я вижу только запрос

http://sy-subrc.blogspot.com/2008/08/sql.html (http://sy-subrc.blogspot.com/2008/08/sql.html)
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Серпень 07, 2009, 09:43:45 ДП
Цитата: Martha від Серпень 07, 2009, 08:35:54 ДП
как посмотреть какие индексы используются? в st05  я вижу только запрос

Кнопка "Explain"
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Серпень 07, 2009, 05:57:04 ПП
Вот мы тут обсуждали, делились опытом, пришли к определенным выводам.......
Самая популярная тема в молодежи  ;)

Только вот сел тут одну прожку делать .... и вижу что не работает как надо .....


Есть выборка

 SELECT SUM( dmbtr ) AS dmbtr bukrs zuonr shkzg hkont blart
 APPENDING CORRESPONDING FIELDS OF TABLE gt_bsis
   FROM bsis
 WHERE
     bukrs IN so_bukrs      AND
     hkont =  '0070300800'  AND
     zuonr IN sa_lifnr      AND
     blart = 'RV' AND
     budat IN so_budat AND
     shkzg = 'H'
     GROUP BY bukrs hkont zuonr  budat shkzg  blart.


У bsis есть три индекса:
Первичный, включающий такие поля:
MANDT   
BUKRS   
HKONT   
AUGDT   
AUGBL   
ZUONR
GJAHR   
BELNR   
BUZEI   

1
MANDT
BUKRS
BELNR
GJAHR
BUZEI

и
"ZAN"
BUKRS
ZUONR
BEWAR

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

Но сие чудо, т.е. SAP чего-то использует последний индекс "ZAN".

Может кто то объяснит мне чего же так? А то моя вера в SAP пошатнулась .....  :)

Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Серпень 07, 2009, 06:06:09 ПП
Проблему решил, убрал из выборки поле "Присвоение" (zuonr), выборка срабатывает мнговенно, предидущая - минут 20 и больше и падала по таймауту ......

Выводы? .....
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Серпень 07, 2009, 06:09:07 ПП
Цитата: Паганель від Серпень 07, 2009, 05:57:04 ПП

 SELECT SUM( dmbtr ) AS dmbtr bukrs zuonr shkzg hkont blart
 APPENDING CORRESPONDING FIELDS OF TABLE gt_bsis
   FROM bsis
 WHERE
     bukrs IN so_bukrs      AND
     hkont =  '0070300800'  AND
     zuonr IN sa_lifnr      AND
     blart = 'RV' AND
     budat IN so_budat AND
     shkzg = 'H'
     GROUP BY bukrs hkont zuonr  budat shkzg  blart.


У bsis есть три индекса:
Первичный, включающий такие поля:
MANDT   
BUKRS   
HKONT   
AUGDT   
AUGBL   
ZUONR
GJAHR   
BELNR   
BUZEI   
А с чего ты взял что первичный должен использоваться? У тебя тут совпадает только  BUKRS и HKONT, дальше все мимо кассы так как значения AUGDT и AUGBL не заданы вообще, то до ZUONR оно вообще не доходит, так что правильно оно его не берет. Ну если ты конечно уверен что нужен именно этот индекс, тогда можно через %_HINTS его задать, если правильно синтаксис помню. Но я бы так не делал, оптимизатору виднее.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Серпень 07, 2009, 09:21:28 ПП
Цитата: Паганель від Серпень 07, 2009, 06:06:09 ПП
Проблему решил, убрал из выборки поле "Присвоение" (zuonr), выборка срабатывает мнговенно, предидущая - минут 20 и больше и падала по таймауту ......

Выводы? .....
Что и требовалось доказать, стал использоваться правильный индекс. Вообще выводы я могу сделать, но они не будут иметь никакого отношения к SAP, а скорее в теории баз данных, будет немного наверное непонятные слова, но это вообще-то не моя задача прочитать курс введение в базы данных  ;). Так вот постараюсь по очень простому. В общем случае если это не хеширование, то индекс это вариации построенные на тему B-дерева, так вот у тебя в ключе данные перечислены в таком порядке

MANDT   
BUKRS   
HKONT   
AUGDT   
AUGBL   
ZUONR
GJAHR   
BELNR   
BUZEI   

А в условии выборки, ты их зада в таком порядке
BUKRS   
HKONT   
<пропущено AUGDT>
<пропущено AUGBL>
ZUONR
<Остальное не важно>

Система при анализе дошла до того что поля AUGDT и AUGBL не заданы, поэтому индекс использоваться не может, а то что ты задал ZUONR, ей по барабану так как по дереву она до него дойти минуя вышестоящие и не определенные AUGDT и AUGBL, никак не может. Кстати твой следующий индекс "ZAN" и подхаватывается потому что идут поля которые есть в индексе и между ними нет пропусков:
BUKRS
ZUONR
<Последние поля не важны BEWAR>, так вот если бы в индексе было вот это BEWAR и оно стояло между BUKRS и ZUONR, но ты его не задавал бы как в предыдущем AUGDT и AUGBL, то у тебя бы и индекс "ZAN" вряд ли бы использовался, получил бы фулскан таблицы.

Поэтому когда ты убрал ZUONR, оно сравнило этих два индекса, в первом есть два поля, во втором только одно.. само собой искать надо по первому.

Про B-дерево для начала тут: http://ru.wikipedia.org/wiki/B-дерево (http://ru.wikipedia.org/wiki/B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE) , хотя там тема большая и вариаций на его тему много.
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Серпень 07, 2009, 10:13:41 ПП
Спасибо, в принципе понятно, немного теории тут точно не помешает.....

Цитата: Uukrul  від Серпень 07, 2009, 09:21:28 ПП
Кстати твой следующий индекс "ZAN" и подхаватывается потому что идут поля которые есть в индексе и между ними нет пропусков:
BUKRS
ZUONR
<Последние поля не важны BEWAR>, так вот если бы в индексе было вот это BEWAR и оно стояло между BUKRS и ZUONR, но ты его не задавал бы как в предыдущем AUGDT и AUGBL, то у тебя бы и индекс "ZAN" вряд ли бы использовался, получил бы фулскан таблицы.

Поэтому когда ты убрал ZUONR, оно сравнило этих два индекса, в первом есть два поля, во втором только одно.. само собой искать надо по первому.

Про B-дерево для начала тут: http://ru.wikipedia.org/wiki/B-дерево (http://ru.wikipedia.org/wiki/B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE) , хотя там тема большая и вариаций на его тему много.

Правда, так и не понял, почему все-таки при выборе индекса, рассматривалось поле zuonr, по моему ситуация в обеих случаях аналогична, в первом индексе есть два поля которые иду подряд, во втором тоже 2 поля, которые идут подряд..... далее идут поля которые присутствуют в условиях выбора но не входят в индекс..... И в первом и во втором случае - одно и тоже .... интересно, как повела бы себя система, если бы было наоборот - в первом индексе было бы поле zuonr, а во втором hkont, что система выбрала бы опять второй? не логично ..... у меня подозрение что тут играет роль еще и то что, поле zuonr больше по длине, естественно, и индекс тоже больше .... хотя первый индекс по количеству полей и может данных, больше ....

Хм, что ли почитать по теории баз данных? Что посоветуешь?  :)

Да точно, сразу после изучения BC400 (если честно и его не читал), надо начинающим абаперам, сразу же читать BC490 (Оптимизация)....
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Серпень 07, 2009, 10:41:28 ПП
Цитата: Паганель від Серпень 07, 2009, 10:13:41 ПП
Правда, так и не понял, почему все-таки при выборе индекса, рассматривалось поле zuonr, по моему ситуация в обеих случаях аналогична, в первом индексе есть два поля которые иду подряд, во втором тоже 2 поля, которые идут подряд..... далее идут поля которые
Ну что тебе сказать... так как слова B-Tree тебе ничего не говорят то как бы сложно объяснить почему оно так берет индексы, я вот попытался но похоже не получилось. Так что проехали.
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Серпень 07, 2009, 11:43:27 ПП
Ок, может на досуге почитаю про твои бе-три  :)
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Серпень 08, 2009, 12:13:51 ДП
Цитата: Паганель від Серпень 07, 2009, 11:43:27 ПП
Ок, может на досуге почитаю про твои бе-три  :)
Да оно только зря время потратишь.. .читать надо что-то про то как строяться индексные файлы в базах данных и далее по нарастающей... а так оно все равно ничего не ясно будет.
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Серпень 08, 2009, 12:15:24 ДП
Цитата: Uukrul  link=topic=174.msg4658#msg4658 date=1249679631
Да оно только зря время потратишь.. .читать надо что-то про то как строяться индексные файлы в базах данных и далее по нарастающей... а так оно все равно ничего не ясно будет.

Может и точно, зачем в такие дебри залазить  :)
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Серпень 10, 2009, 01:04:41 ПП
Опять я с теми же вопросами, делаю ту же выборку, только поменял № счета и вид документа, и снова выборка не отрабатывает за 20 мин.


    SELECT SUM( dmbtr ) AS dmbtr bukrs zuonr shkzg hkont blart
  APPENDING CORRESPONDING FIELDS OF TABLE gt_bsis
    FROM bsis
  WHERE
      bukrs IN so_bukrs      AND
      hkont = '0063109900' AND
      blart = 'WA'     AND
      budat IN so_budat         AND
      shkzg = 'H'
      GROUP BY bukrs hkont zuonr  budat shkzg  blart.


Уже все мозги сломал, где что не так?
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Серпень 10, 2009, 01:09:51 ПП
Цитата: Паганель від Серпень 10, 2009, 01:04:41 ПП
Опять я с теми же вопросами, делаю ту же выборку, только поменял № счета и вид документа, и снова выборка не отрабатывает за 20 мин.
Ну план запроса однако давай... какие индексы потянулись, какие есть?
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Серпень 10, 2009, 01:40:00 ПП
Не получается просмотреть трасировку, выборка падает по таймату, и в трассировке не видно данных про выборку с bsis..... очень странно .....

Самое странное, стоит поменять номер счета на такой же как в предидущем примере, и все работает очень быстро........ разница в данных только в том что для счета 0063109900 не заполняется поле zuonr

Так работает быстро (но не правильно)

 SELECT SUM( dmbtr ) AS dmbtr bukrs zuonr shkzg hkont blart
 APPENDING CORRESPONDING FIELDS OF TABLE gt_bsis
   FROM bsis
 WHERE
     bukrs IN so_bukrs      AND
     hkont ='0070300800'    AND    
     blart = 'WA'           AND
     budat IN so_budat        AND
     shkzg = 'H'
     GROUP BY bukrs hkont zuonr  budat shkzg  blart.


А так сильно долго работает:

 SELECT SUM( dmbtr ) AS dmbtr bukrs zuonr shkzg hkont blart
 APPENDING CORRESPONDING FIELDS OF TABLE gt_bsis
   FROM bsis
 WHERE
     bukrs IN so_bukrs      AND
     hkont ='0063109900' AND
     blart = 'WA'           AND
     budat IN so_budat        AND
     shkzg = 'H'
     GROUP BY bukrs hkont zuonr  budat shkzg  blart.


Для первого запроса - трасировка на рис. ниже
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Серпень 10, 2009, 02:21:07 ПП
Можно сказать что проблему решил, выборка валилась из-за очень больших объемов данных, данный счет у нас перерасчетный, и проводки по нему возникали по каждой позиции документа материала, определенного вида ......
Попробую сделать аналогичную выборку через faglflext

Спасибо за помощь и участие.
Назва: Re: Оптимизация ABAP-а
Відправлено: Удав від Серпень 10, 2009, 02:32:56 ПП
Большой объем данных никак не влияет на выбор индекса :)
Попробуй включить в запрос и group by поля augbl и augdt (в условии задавать для них пустые значения ("" для augbl и "00000000" для augdt)
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Серпень 10, 2009, 03:51:31 ПП
Цитата: Удав від Серпень 10, 2009, 02:32:56 ПП
Большой объем данных никак не влияет на выбор индекса :)
Та ему не поможет... у него данных он же говорит по счету много, так что падать будет при любом раскладе для этого счета.
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Серпень 10, 2009, 04:50:03 ПП
Да вряд ли поможет  :(
..............................
Не помогло, но за советы все равно - Спасибо
Назва: Re: Оптимизация ABAP-а
Відправлено: Удав від Серпень 10, 2009, 05:06:51 ПП
Цитата: Uukrul  link=topic=174.msg4669#msg4669 date=1249908691
Та ему не поможет... у него данных он же говорит по счету много, так что падать будет при любом раскладе для этого счета.
не факт :)
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Серпень 10, 2009, 05:17:19 ПП
Цитата: Удав від Серпень 10, 2009, 05:06:51 ПП
не факт :)
Да у него дамп из-за памяти, а не времени выборки, так что факт  ::) или есть способ динамического сжатия выбираемой информации  на леут  ;D
Назва: Re: Оптимизация ABAP-а
Відправлено: Удав від Серпень 10, 2009, 05:43:11 ПП
Да ладно  ???
SELECT SUM( dmbtr ) AS dmbtr bukrs zuonr shkzg hkont blart
  APPENDING CORRESPONDING FIELDS OF TABLE gt_bsis
    FROM bsis
  WHERE
      bukrs IN so_bukrs      AND
      hkont =  '0070300800'  AND
      zuonr IN sa_lifnr      AND
      blart = 'RV' AND
      budat IN so_budat AND
      shkzg = 'H'
      GROUP BY bukrs hkont zuonr  budat shkzg  blart.

Ширина выборки - 50 байт.
Это же сколько нужно записей выбрать, чтобы лимита памяти достичь :)
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Серпень 10, 2009, 05:52:51 ПП
Цитата: Удав від Серпень 10, 2009, 05:43:11 ПП
Это же сколько нужно записей выбрать, чтобы лимита памяти достичь :)
Ну так кто ж его знает какая у него там машинка стоит и сколько памяти на процесс выделено... и что у него еще в памяти крутиться кроме этого запроса. Кстати у него ритейл, так что... количество документов там может быть ну очень большим.
Назва: Re: Оптимизация ABAP-а
Відправлено: Удав від Серпень 10, 2009, 06:21:09 ПП
Ну как... 2000000 счетов-фактур. Если в документах содержится по 1-й позиции требуемого бухгалтерского счета, то это ~100 МБ. Если даже по 10 - это ~1 ГБ.
Если на выделение памяти для процесса ограничение 500 МБ (ztta/roll_extension), то для приведенного примера нужно использовать конструкцию SELECT .. PACKAGE SIZE, которая позволяет выгружать данные во внутреннюю таблицу порциями.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Серпень 10, 2009, 08:01:13 ПП
Цитата: Удав від Серпень 10, 2009, 06:21:09 ПП
Если на выделение памяти для процесса ограничение 500 МБ (ztta/roll_extension), то для приведенного примера нужно использовать конструкцию SELECT .. PACKAGE SIZE, которая позволяет выгружать данные во внутреннюю таблицу порциями.
Вот сейчас автора запроса придет и узнаем что у него там на процесс выделено...
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Серпень 10, 2009, 09:34:46 ПП
Ага, узнаете  :)...... про.....возился  :)  с данным запросом ..... не получится, ну очень много документиков, реально берем 200 магазинов (отдельные заводы), половина продаж это как раз нужные мне (консигнация), данный счет содержит проводки по перерасчетному счету для сохранения себестоимости реализованного товара, представь выторг крупных торговых сетей,  по алкоголю, и на каждую позицию товара (материала) создается проводка по нужному мне счету .....  :), лучше можно было придумать только "полная выборка bseg" меня админы потом медленно четвертуют  :)

PS (Uukrul): Отредактировано по просьбе Паганеля.
Назва: Re: Оптимизация ABAP-а
Відправлено: Martha від Серпень 11, 2009, 08:58:11 ДП
Цитата: tav_48 від Серпень 07, 2009, 09:42:00 ДП
http://sy-subrc.blogspot.com/2008/08/sql.html (http://sy-subrc.blogspot.com/2008/08/sql.html)

идеальное пояснение. простите за глупый вопрос, а для чего используется se30  и если можно что-то похожее в качестве пояснения.
спасибо
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Серпень 11, 2009, 09:15:30 ДП
Ну с помощью se30 можно производить поиск "узких мест" в программе, т.е. тех которые выполняются слишком долго  :)
Назва: Re: Оптимизация ABAP-а (SELECT * ENDSELECT.)
Відправлено: Martha від Вересень 02, 2009, 04:18:22 ПП
Цитата: Uukrul  від Травень 19, 2008, 10:39:05 ДП
Самый тормознутый способ выборки чего либо из таблиц это операция:

SELECT * FROM mard.
ENDSELECT.

Однако исключать данный способ из применения не следует, так как он дает наименьшую нагрузку на сервер + минимальное использование памяти. Так что если таблица небольшая или выборка данных будет небольшой, то вполне можно обойтись и данной конструкцией, т.е. без операции SELECT * INTO TABLE и дальнейшим LOOP AT lt_tab. ENDLOOP.  Ну и как обычно смотрим трассировку запросов. Если эта конструкция является самой тормознутой в вашем приложении, то имеет смысл ее заменить, а иначе, нефиг заниматься оптимизацией так где и без нее все бегает  ;)

стоит задача оптимизации чужой программы.
она вся написана следующим образом:

SELECT * FROM <таб1> WHERE <по какому-то индексу>.
*пара экранов каких-то действий, включая  штук  5
   Select single *  from <таб2> where <ключ>
     *Из разных таблиц

И пару
        SELECT * FROM Z### WHERE  <field_key> = <значение>.
           * какие-то действия
        ENDSELECT. 
     * какие-то действия
   ENDSELECT.   


Как ее оптимизировать:
Например:

  SELECT * FROM BSEG WHERE BUKRS = ZBUKRS
                           AND GJAHR = ZGJAHR
                           AND BELNR = itab-BELNR
                   AND ( ( SHKZG = '##' AND XNEGP = '##' ) OR
                       ( SHKZG = '@@' AND XNEGP = '@@' ) ).

        SELECT * FROM Z### WHERE  <field_key> = <значение>.
           * какие-то действия
        ENDSELECT. 
* какие-то действия
  ENDSELECT.   


Из светлых мыслей на эту тему замена select по bseg на:

types: begin of t_bseg,
только необходимые нам поля
      end of t_bseg.
data: i_bseg type standard table of t_bseg with header line.

clear i_bseg[].
      SELECT <только необходимые нам поля> FROM BSEG
              WHERE BUKRS = ZBUKRS
                AND GJAHR = ZGJAHR
                AND BELNR = itab-BELNR
                AND ( ( SHKZG = '##' AND XNEGP = '##' ) OR
                    ( SHKZG = '@@' AND XNEGP = '@@' ) ).
      loop at i_bseg.
        SELECT * FROM Z### WHERE  <field_key> = <значение>.
           * какие-то действия
        ENDSELECT. 
     * какие-то действия
      Endloop.


1. стоит ли заменять select endselect  на внутренние таблицы

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

Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Вересень 02, 2009, 04:37:38 ПП
Существует 2 случая, когда использование конструкции SELECT/ENDSELECT оправдано:
1) Нехватка выделенной пользователю памяти, т.е. внутренняя таблица после выборки SELECT ... INTO TABLE ... превышает установленный базисниками объем памяти на Application server, в результате чего программа падает в дамп.
2) Очень маленький объем выбираемых данных (вспомогательных), если лень объявлять вн. таблицу и затем писать LOOP/ENDLOOP.

Для оптимизации циклов LOOP/ENDLOOP также рекомендуется использование FIELD-SYMBOLS если вн. таблица модифицируется.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Вересень 02, 2009, 04:57:28 ПП
Цитата: Dmitriy від Вересень 02, 2009, 04:37:38 ПП
Для оптимизации циклов LOOP/ENDLOOP также рекомендуется использование FIELD-SYMBOLS если вн. таблица модифицируется.
Даже если она не модифицируется это будет быстрее...
Назва: Re: Оптимизация ABAP-а
Відправлено: Martha від Вересень 08, 2009, 03:01:10 ПП
Для оптимизации некоторых select join   раньше использовала ракурсы БД по соответствующим таблицам (без фанатизма, конечно) . т.е. mkpf+mseg  или lips+likp. В местной системе обнаружила некое кол-во ракурсов на интересующую меня тему, но с разным набором полей.   Что оптимально: создать ракурс с большим кол-вом полей и использовать его в разных программах или держать несколько ракурсов под разные нужды. Как создание ракурса увеличивает нагрузку на БД.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Вересень 08, 2009, 03:47:35 ПП
Цитата: Martha від Вересень 08, 2009, 03:01:10 ПП
Для оптимизации некоторых select join   раньше использовала ракурсы БД по соответствующим таблицам (без фанатизма, конечно) . т.е. mkpf+mseg  или lips+likp. В местной системе обнаружила некое кол-во ракурсов на интересующую меня тему, но с разным набором полей.   Что оптимально: создать ракурс с большим кол-вом полей и использовать его в разных программах или держать несколько ракурсов под разные нужды. Как создание ракурса увеличивает нагрузку на БД.
Оно конечно неплохо бы проверить, но мне кажется что несколько ракурсов с узкими наборами полей будут немного быстрее чем одни ракурс объединяющий все поля из нескольких ракурсов. С точки же нагрузки, ракурс это подготовленный запрос к базе данных и все, т.е. теоретически его вызов быстрее чем просто запрос, но в рамках SAP, на это можно забить. Вообще-то идея ракурсов была в том чтобы скрыть структуру базы данных от приложения, т.е. например если у вас изменилась схема базы данных (но не сами данные), то перестроив ракурс, приложение пользователя не заметит таких изменений и продолжит работу.
Назва: Re: Оптимизация ABAP-а
Відправлено: Martha від Вересень 08, 2009, 04:22:55 ПП
Цитата: Uukrul  link=topic=174.msg4866#msg4866 date=1252414055
Вообще-то идея ракурсов была в том чтобы скрыть структуру базы данных от приложения, т.е. например если у вас изменилась схема базы данных (но не сами данные), то перестроив ракурс, приложение пользователя не заметит таких изменений и продолжит работу.

т.е. join  лучше обходить без использования ракурсов?
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Вересень 08, 2009, 05:12:42 ПП
Цитата: Martha від Вересень 08, 2009, 04:22:55 ПП
т.е. join  лучше обходить без использования ракурсов?
Ну я не могу так сказать что лучше без ракурсов, просто ракурс для своей программы вещь как по мне не очень нужная и необходимая, но опять же смотря какая программа и кто ее пишет и сколько людей в этом участвуют. Выигрыша в производительности особого, да и не особого не будет.
Назва: Re: Оптимизация ABAP-а
Відправлено: Martha від Вересень 09, 2009, 08:55:33 ДП
есть код, в котором прописаны константы. как оптимально их убрать?
(как вариант  - завести внутреннюю таблицу , доступную избранному человеку или есть другой хороший способ)
например:

SELECT * FROM A596
          into table ia596
        WHERE KAPPL = '# ' AND
                KSCHL = '####' AND
                VKORG = '####' AND  PLTYP = '##'
                AND WAERK = '###' AND MATNR =  MATNR .


и просто в коде много всяких констанкт для исключений и пр.

вообще стоит ли их куда-нибудь в отдельное место перемещать?
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Вересень 09, 2009, 09:43:47 ДП
Цитата: Martha від Вересень 09, 2009, 08:55:33 ДП
есть код, в котором прописаны константы. как оптимально их убрать?
(как вариант  - завести внутреннюю таблицу , доступную избранному человеку или есть другой хороший способ)
например:
Тут варианты сложно вам предложить, все зависит от задачи. Внутренняя таблица со значениями, ну это если у вас есть какие-то варианты работы, а если вариантов нет, т.е. у вас например вид документа всегда NB, тогда используйте константы в запросе и в принципе таблица не нужна, ну можно для наглядности завести в заголовке программы что-то типа:

CONSTANTS: cns_doc_type LIKE ekko-ebeln VALUE 'NB'

Ну и дальше в запросах использовать

... WHERE ebeln = cns_doc_type ...

Если документ измениться то всегда можно быстро изменить только значение константы. Таблицу для такого я бы использовал только в случае если отчет предполагается тиражировать в разные системы, разным клиентам.
Назва: Re: Оптимизация ABAP-а
Відправлено: Удав від Вересень 10, 2009, 12:10:25 ПП
Цитата: Martha від Вересень 08, 2009, 03:01:10 ПП
Для оптимизации некоторых select join   раньше использовала ракурсы БД по соответствующим таблицам (без фанатизма, конечно) . т.е. mkpf+mseg  или lips+likp. В местной системе обнаружила некое кол-во ракурсов на интересующую меня тему, но с разным набором полей.   Что оптимально: создать ракурс с большим кол-вом полей и использовать его в разных программах или держать несколько ракурсов под разные нужды. Как создание ракурса увеличивает нагрузку на БД.
В результате практических наблюдений было выяснено, что для БД Oracle 9 выборка с одинаковым составом полей и условиями
1. по по MKPF+MSEG идет быстрее, чем по ракурсу WB2_V_MKPF_MSEG2
2.По likp+lips, vbak+vbap, ekko+ekpo идет медленнее, чем по соответствующим ракурсам.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Вересень 10, 2009, 12:12:25 ПП
Цитата: Удав від Вересень 10, 2009, 12:10:25 ПП
1. по по MKPF+MSEG идет быстрее, чем по ракурсу WB2_V_MKPF_MSEG2
2.По likp+lips, vbak+vbap, ekko+ekpo идет медленнее, чем по соответствующим ракурсам.
А приблизительную разницу в скорости можно озвучить? Ну там 2-3% или 10%?
Назва: Re: Оптимизация ABAP-а
Відправлено: Удав від Вересень 10, 2009, 12:54:53 ПП
Цитата: Martha від Вересень 09, 2009, 08:55:33 ДП
есть код, в котором прописаны константы. как оптимально их убрать?
(как вариант  - завести внутреннюю таблицу , доступную избранному человеку или есть другой хороший способ)
например:

SELECT * FROM A596
          into table ia596
        WHERE KAPPL = '# ' AND
                KSCHL = '####' AND
                VKORG = '####' AND  PLTYP = '##'
                AND WAERK = '###' AND MATNR =  MATNR .


и просто в коде много всяких констанкт для исключений и пр.

вообще стоит ли их куда-нибудь в отдельное место перемещать?
Орг.единицы лучше помещать на экран выбора отчета.
Виды условий и прочие поля, которые не должны меняться, лучше оформить константами, как сказал Uurkul
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Вересень 10, 2009, 11:47:59 ПП
Цитата: Martha від Вересень 09, 2009, 08:55:33 ДП
есть код, в котором прописаны константы. как оптимально их убрать?
(как вариант  - завести внутреннюю таблицу , доступную избранному человеку или есть другой хороший способ)
например:

SELECT * FROM A596
         into table ia596
       WHERE KAPPL = '# ' AND
               KSCHL = '####' AND
               VKORG = '####' AND  PLTYP = '##'
               AND WAERK = '###' AND MATNR =  MATNR .


и просто в коде много всяких констанкт для исключений и пр.

вообще стоит ли их куда-нибудь в отдельное место перемещать?
Собственно, варианты «устранения» хардкода уже перечислены, резюмируем...

1. Вынос на селекционный экран. Заполнение/изменение: сохранение варианта отчета и последующий его вызов запуском транзакции, или программно до вывода экрана (коррелирует с п.2). Поля можно сделать нередактируемыми или скрыть для обычных пользователей (выводить для редактирования только при наличии полномочий) и т.п., т.е. существуют вариации. Изменение константы может быть завязано как на ответственного ("избранного" ;D) пользователя, так и на абапера.
2. Вынос в константы. Изменение завязано исключительно на абапера.
3. Вынос в таблицу БД, генерация диалога её ведения, интерфейса загрузки из файла для первоначального заполнения, если данных много (пример: таблица "статья - счета" для баланса, отчета о ПиУ в бухгалтерии и др.), создание объекта полномочий для ответственных пользователей. Изменение завязано на ответственного пользователя.

Выбор варианта зависит от условий каждой конкретной задачи.
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Вересень 12, 2009, 09:42:29 ДП
Привет всем.

Извиняюсь что не так часто сейчас захожу теперь в эту интересную тему, тут просто проект стартанунл, тут и спать некогда :).

Спасибо за идеии, как только освобожусь, возьмусь снова за абапчик, задачу то сделать надо.

Теперь правда проблема не с bsis, а с первой выборкой по mkpf+mseg, не успевает зараза отработать.

Думаю попробовать пару идей подкинутых вами:

- SELECT .. PACKAGE SIZE - вдруг валится из-за памяти (хотя ошибка TIME_OUT)
- может попробовать SELECT .... ENDSELECT.


Кстати, тут уже говорили что можно сбрасывать время тайоута, используя commit work, как Вы думаете: можно ли использовать его в SELECT .... ENDSELECT, будет ли работать?


- попробую использовать mkol + mkolh - правда еще не копал, каким же образом юзать эту связку, нету ли у кого-то примера?
Назва: Re: Оптимизация ABAP-а
Відправлено: Удав від Вересень 17, 2009, 11:56:34 ДП
Посмотри решения в нотах 902157 (https://service.sap.com/sap/support/notes/902157) и 902675 (https://service.sap.com/sap/support/notes/902675).
Назва: Re: Оптимизация ABAP-а
Відправлено: Паганель від Вересень 17, 2009, 03:48:01 ПП
Цитата: Удав від Вересень 17, 2009, 11:56:34 ДП
Посмотри решения в нотах 902157 (https://service.sap.com/sap/support/notes/902157) и 902675 (https://service.sap.com/sap/support/notes/902675).

Спасибо, почитаю
Назва: Re: Оптимизация ABAP-а
Відправлено: darth від Вересень 23, 2009, 09:54:50 ДП
мои 20 тугриков  :)
--
select в sorted table намного быстрее, чем
select в standard (или не дай бог with header line) + sort
только что замерял:
sorted 1774,
standard+sort 75479,
замерял на AUFK (~15000 записей)
--
для чего сортировка? - что потом read....binary search
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Вересень 23, 2009, 10:24:46 ДП
Welcome, darth!
Здрав будь, ждем от тебя дальнейших сообщений для ликбеза по матчасти. ;)
Назва: Re: Оптимизация ABAP-а
Відправлено: darth від Вересень 23, 2009, 11:21:28 ДП
еще интересная фича...
в случае когда нам в цикле (например по fi-документам, очень много записей) нужно к каждому кредитору вытащить наименование (причем кредиторов заведомо намного меньше чем документов).
в принципе есть несколько вариантов реализации, наиболее быстрым мне кажется следующий:
* Наименование кредитора
TYPES: BEGIN OF t_lfa1,
      lifnr TYPE lifnr,
      name1 TYPE name1_gp,
        END OF t_lfa1.
DATA: gs_lfa1 TYPE t_lfa1,
     gt_lfa1 TYPE SORTED TABLE OF t_lfa1
             WITH UNIQUE KEY lifnr.
DATA: gt_report TYPE TABLE OF bseg,
     gs_report TYPE bseg.
FIELD-SYMBOLS: <fs_lfa1> LIKE LINE OF gt_lfa1.
* --------------------------------------------
LOOP AT gt_report INTO gs_report.
* Какой-либо код
* ..............
* Какой-либо код
 IF report-lifnr IS NOT INITIAL.
* тут SELECT SINGLE заменим на хитрую конструкцию
    UNASSIGN <fs_lfa1>. " Dump off
   READ TABLE gt_lfa1 ASSIGNING <fs_lfa1> WITH KEY
                lifnr = gs_report-lifnr BINARY SEARCH.
   IF sy-subrc <> 0.
* Не нашли однако! надо селектнуть и добавить по индексу,
* который определил read (он установил SY-TABIX именно в то место,
* где в сортированной таблице должна была быть запись)!
     IF <fs_lfa1> IS NOT ASSIGNED.
       ASSIGN gs_lfa1 TO <fs_lfa1>.
     ENDIF.
     SELECT SINGLE name1 INTO <fs_lfa1>-name1 FROM lfa1
      WHERE lifnr = gs_report-lifnr.
     IF sy-subrc = 0.
       <fs_lfa1>-lifnr = gs_report-lifnr.
       INSERT <fs_lfa1> INTO gt_lfa1 INDEX sy-tabix.
     ENDIF.
   ENDIF.
   gs_report-lifname = <fs_lfa1>-name1.
 ENDIF.
* Какой-либо код
* Модификация основной таблицы GT_REPORT
* Какой-либо код
ENDLOOP.
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Вересень 23, 2009, 11:37:48 ДП
Т.е. смысл в том, что мы не выбираем сразу всю таблицу LFA1 во внутреннюю gt_lfa1 (как этому учил нас ну ты помнишь кто ;)), а делаем это по необходимости, постепенно, в процессе цикла по позициям д-тов FI, экономя тем самым время и память, поскольку все кредиторы не понадобятся...

P.S. Уже не помню, писал или нет, что для экономии памяти после обработки делать FREE уже "ненужных" вн. таблиц со вспомогательными данными (наименования и пр.). Если, конечно, это критично.

Добавлено: надо будет откатать решение и подредактировать свой пост про это дело...
Назва: Re: Оптимизация ABAP-а
Відправлено: darth від Вересень 23, 2009, 11:46:09 ДП
да, выбирать всю немного накладно - вдруг их там много (например у меня 40тысяч),
выбирать с for all enrtyes - тоже геморно, т.к. в таблице доков (по которой будет for all enrtyes)
например 200 тысяч позиций, да еще и ПОВТОРЯЮТСЯ кредиторы (это очень важно что они повторяются - вышеупомянутым кодом мы уходим от повторения!)
Назва: Re: Оптимизация ABAP-а
Відправлено: darth від Вересень 23, 2009, 11:59:43 ДП
еще интересная возможность...
иногда берет сомнение какой вариант кода отработает быстрее...
можно довольно быстро и корректно замерить (например два варианта одного селекта)
в транзакции SE30,
заходим в нее и нажимаем сверху кнопку "советы",
видим два окошечка - в каждом можно написать (вставить из буфера) кусок кода,
нажав кнопку наверху "Измерить время выполнения" мы увидим над каждым из окон время выполнения.
--
причем можно сравнивать не только свои проги, но и выбрать в дереве слева примеры по быстродействия SAP...
Назва: Re: Оптимизация ABAP-а
Відправлено: darth від Вересень 23, 2009, 12:25:16 ПП
кхм... в коде косячок есть небольшой - а поправить свое сообщение я не могу - страннаааа...  ???

Dmitriy: подправил, структурировал немного. Просто время, отпущенное для редактирования своего сообщения ограничено. ;)
Назва: Re: Оптимизация ABAP-а
Відправлено: Удав від Вересень 23, 2009, 04:00:05 ПП
Цитата: darth від Вересень 23, 2009, 11:21:28 ДП
еще интересная фича...
в случае когда нам в цикле (например по fi-документам, очень много записей) нужно к каждому кредитору вытащить наименование (причем кредиторов заведомо намного меньше чем документов).
Самым быстрым будет использование сортированной таблицы (SORTED TABLE) с уникальным ключом
Тогда не придется дополнительно искать, куда вставить запись. ;)
Назва: Re: Оптимизация ABAP-а
Відправлено: darth від Вересень 23, 2009, 04:29:33 ПП
она и так сортированная и с уникальным ключом (см код)...
при sy-subrc <> 0 после чтения из нее..
sy-tabix содежит тот индекс где должна была б находиться запись - это очень интересный момент (специально сегодня этот прикол проверял)! вставка по индексу быстрее просто вставки в сортированную таблицу.
Назва: Re: Оптимизация ABAP-а
Відправлено: Удав від Вересень 24, 2009, 10:27:45 ДП
настолько, что выгоднее писать дополнительный код? :)
Назва: Re: Оптимизация ABAP-а
Відправлено: darth від Вересень 24, 2009, 10:39:36 ДП
время будет - замеряю  ;)
Назва: Re: Оптимизация ABAP-а
Відправлено: darth від Вересень 25, 2009, 01:44:09 ПП
только что проверил:
1. insert без инекса в сортированную таблицу не работает!
2. append работает, но только в том случае, если данные выбираются в порядке сортировки,
  т.е. таблица по которой loop остортирована также как предполагается в sorted table,
  попробовав отсортировать gt_report descending (тогда как sorted gt_lifnr1 ascending) попал
  в дамп. (это связано с тем, что аппенд добавляет в конец таблицы, не смотря на то что она
   sorted, и байнари серч найдя значение 5, уже ек идет дальше в поиске нужного значения 4,
   и пото пытается вставить 4, сортировать же gt_report как раз не хочется - ибо он очень
   большой, так что insert по индексу мне видится наиболее разумным решением).
см код...

REPORT  ZTEST_12                                .
                       .
* Наименование кредитора
TYPES: BEGIN OF t_lfa1,
      lifnr TYPE lifnr,
      name1 TYPE name1_gp,
        END OF t_lfa1.
DATA: gs_lfa1 TYPE t_lfa1,
     gt_lfa1 TYPE SORTED TABLE OF t_lfa1
             WITH UNIQUE KEY lifnr.
DATA: gt_lfa_main TYPE standard TABLE OF t_lfa1,
     gs_report TYPE t_lfa1.
FIELD-SYMBOLS: <fs_lfa1> LIKE LINE OF gt_lfa1.
* --------------------------------------------

select lifnr
 into table gt_lfa_main
 from lfa1
*  up to 10000 rows
.
sort gt_lfa_main by lifnr DESCENDING.

LOOP AT gt_lfa_main INTO gs_report.
* Какой-либо код
* ..............
* Какой-либо код
 IF gs_report-lifnr IS NOT INITIAL.
* тут SELECT SINGLE заменим на хитрую конструкцию
   UNASSIGN <fs_lfa1>. " Dump off
   READ TABLE gt_lfa1 ASSIGNING <fs_lfa1> WITH KEY
                lifnr = gs_report-lifnr BINARY SEARCH.
   IF sy-subrc <> 0.
* Не нашли однако! надо селектнуть и добавить по индексу,
* который определил read (он установил SY-TABIX именно в то место,
* где в сортированной таблице должна была быть запись)!
     IF <fs_lfa1> IS NOT ASSIGNED.
       ASSIGN gs_lfa1 TO <fs_lfa1>.
     ENDIF.
     SELECT SINGLE name1 INTO <fs_lfa1>-name1 FROM lfa1
      WHERE lifnr = gs_report-lifnr.
     IF sy-subrc = 0.
       <fs_lfa1>-lifnr = gs_report-lifnr.
       append <fs_lfa1> TO gt_lfa1.
     ENDIF.
   ENDIF.
   gs_report-name1 = <fs_lfa1>-name1.
 ENDIF.
* Какой-либо код
* Модификация основной таблицы GT_REPORT
* Какой-либо код
ENDLOOP.
Назва: Re: Оптимизация ABAP-а
Відправлено: Удав від Вересень 25, 2009, 02:26:36 ПП
Я имел в виду, что нужно сразу работать с таблицей типа SORTED TABLE  :)
С такой INSERT .. INTO TABLE работает на "ура".
Назва: Re: Оптимизация ABAP-а
Відправлено: darth від Грудень 14, 2009, 01:44:11 ПП
как правильнее организовать цикл по большой внутренней таблице с условиями:
Код:

tables: bkpf.

data: itab type sorted table of bkpf
                with unique key bukrs belnr gjahr.

field-symbols: <itab> like line of itab.


select * into table itab from bkpf
                         where bukrs eq 'SNNG'
                           and gjahr eq '2007'.

data: t1 type i,
      t2 type i,
      t3 type i,
      t4 type i.

data: delta type i.

* ВАРИАНТ 1 ---------------------------------------------------------&
get run time field t1.
loop at itab assigning <itab>
             where bukrs eq 'SNNG'
               and belnr cp '55*'.
endloop.

* ВАРИАНТ 2 ---------------------------------------------------------&
get run time field t2.
read table itab transporting no fields
                with key bukrs = 'SNNG'
                         belnr = '5500000000'
                binary search.

loop at itab assigning <itab> from sy-tabix.
  if <itab>-belnr+0(2) <> '55'.
    exit.
  endif.
endloop.

* ВАРИАНТ 3 ---------------------------------------------------------&
get run time field t3.
read table itab transporting no fields
                with key bukrs = 'SNNG'
                         belnr = '5500000000'
                binary search.

loop at itab assigning <itab>
             from sy-tabix
             where bukrs eq 'SNNG'
               and belnr cp '55*'.
endloop.

get run time field t4.

* результат сравнения -----------------------------------------------&
delta = t2 - t1.
write: / 'ASSIGNING + WHERE: ', delta.

delta = t3 - t2.
write: / 'ASSIGNING + FROM + IF: ', delta.

delta = t4 - t3.
write: / 'ASSIGNING + FROM + WHERE: ', delta.

как не странно но очень большая разница между этими тремя реализациями...
loop по сортированный таблице работает не так быстро как думается...
лучший по быстродействию вариант - 2, причем на порядки!!!
при объеме таблицы в 40 000 записей
ASSIGNING + WHERE:      43.548       
ASSIGNING + FROM + IF:       727   
ASSIGNING + FROM + WHERE:       1.849
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Жовтень 25, 2010, 12:14:24 ДП
В общем-то, так как тема оказалась большая и интересная, то все что можно было собрать, собрано, посчитано и описано в документе: "Оптимизация ABAP v1-0.pdf", первая версия данного документа выложена в первом посте данной темы: http://sapforum.biz/index.php/topic,174.msg713.html#msg713 и в случае обновлений файл будет так же изменяться по этому же адресу.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Березень 21, 2011, 05:31:38 ПП
Подготовлена новая версия документа 1.1 по оптимизации ABAP. Файл выложен в первом посте данной темы: http://sapforum.biz/index.php/topic,174.msg713.html#msg713. Так что если есть замечания и комментарии, пишем  ::)
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Квітень 25, 2011, 02:48:52 ПП
Некоторые ссылки в помощь...
ABAP Performance and Tuning (http://forums.sdn.sap.com/forum.jspa?forumID=234) - оптимизация на SDN
What Is New in ABAP Language, ABAP Workbench, and Enhancement Framework With SAP NetWeaver 7.0 EhP2 (http://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/18115) - полезная инфа
SAT вместо SE30 (http://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/18209) - транзакция SAT
ЦитатаSAT is the transaction name of the new ABAP Runtime Analysis Tool, which is one of the most significant improvements in ABAP in the NetWeaver 7.0 EhP2. For those of you who are already familiar with the transaction SE30, the former ABAP Runtime Analysis Tool, transaction SAT is the successor of SE30. In SAT, ABAP's Runtime Analysis has been reworked by SAP's R&D department and has been enhanced with effective new analysis tools and features.

SAT offers benefits such as a modern state-of-the art UI, new analysis tools, easy navigation between tools and so on. This first blog of the series about SAT gives overview of the most useful SAT improvements (particularly in comparison with the former SE30) and gives a quick guideline how to use new features and tools of the SAT to execute effective runtime analysis of any ABAP application.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Травень 20, 2011, 09:40:28 ПП
Наверное это я вставлю в самом начале следующей версии документа:
Цитата
В финансах как и в жизни, есть так называемый принцип уместности или в народе, овчинка должна стоит выделки, или если еще ближе к теме, то не надо оптимизировать то, что в оптимизации не нуждается. Хотите пример.. ну что ж никто не оценит если вы потратите пару дней на оптимизацию в результате которой программа вместо часа будет работать 55 минут, поверьте - пользователи этого не поймут и не оценят, а вот два дня вашей работы... ну как по мне они этого не стоят, хотя если вам больше нечем заняться, то оптимизируйте конечно  ::)
Назва: Re: Оптимизация ABAP-а (SLIN – Расширенная проверка программы)
Відправлено: Uukrul від Вересень 11, 2011, 09:32:37 ПП
Простая транзакция, которая позволяет быстро выполнить проверку качества написанного кода для программы. Стандартно можно быстро проверить простые отчеты, если нужно проверить что-то более глобальное, то следует использовать транзакцию «Инспектор кода SAP». Программу можно проверить или запустив отдельно транзакцию SLIN или же находясь в инспекторе кода, например транзакция SE38 – ABAP редактор, выполнить по меню следующий пункт: «Программа» – «Проверить» – «Расширенная проверка программы».  При этом если вы находитесь в одном из модулей программы, то система проверку начнем с базового модуля. Например, имеем отчет, который определенным способом выбирает документы резервирований, программа типа отчет, включает в себя несколько модулей, по которым разнесена логика работы. Находясь в редакторе кода, выбираем расширенную проверку программы, рисунок SE38-1.png. Будет запущена транзакция SLIN, куда будет автоматически подставлено имя программы находящейся в редакторе кода в текущий момент. По умолчанию большинство позиций будет отмечено для расширенной проверки, рисунок SLIN-0.png. Любая расширенная проверка вашей программы, покажет, что с точки зрения системы SAP, вы писать правильно не умеете, если до этого у вас нет привычки, запускать расширенную проверку для всех своих текстов. 

Запустим проверку, отметив все галки в блоке «Проверки». Получим таблицу со списком данных проверки. Так как сам по себе проверяемый отчет не слишком большой, то в данном случае совсем уже критических предупреждений сравнительно не много, рисунок SLIN-1.png. Данные в таблице сгруппированы в три колонки, первая колонка содержит операции, которые с точки зрения системы являются критическими, далее идет колонка предупреждений и последняя колонка содержит информационные сообщения, когда вроде как все хорошо, но системе есть что вам сказать интересного. Для просмотра детальной информации нужно сделать двойной клик мышью в интересующем поле и система перейдет к экрану детальной информации по проблемам.

PS: Если у кого есть примеры ошибок которые не описаны дополняйте.
PSS: В файл по оптимизации данная информация будет перенесена чуть позже в более расширенном виде.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Вересень 21, 2011, 04:44:04 ПП
Выложена промежуточная версия Оптимизация ABAP 1.2, в которой частично расширено описание раздела 10 – Тестирование программ, дополнено описанием использования транзакций расширенной проверки программы SLIN и анализатора код транзакции SCI / SCII. Как обычно файлик прикреплен в первом посте данной темы.
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Вересень 21, 2011, 04:47:45 ПП
Цитата: Uukrul від Вересень 21, 2011, 04:44:04 ПП
Выложена промежуточная версия Оптимизация ABAP 1.2 В которой частично расширено описание раздела 10 – Тестирование программ, дополнено описанием использования транзакций расширенной проверки программы SLIN и анализатора код транзакции SCI / SCII.
Всё пишешь, брат... 8)

P.S. Надо бы подъехать к тебе, успокоить, так тЕбе же фиг успокоишь)))
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Вересень 21, 2011, 04:49:03 ПП
Цитата: Dmitriy від Вересень 21, 2011, 04:47:45 ПП
Всё пишешь, брат... 8)
Ну настоящему джентльмену всегда есть что по чем сказать  :P
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Вересень 22, 2011, 10:50:23 ДП
Цитата: Dmitriy від Вересень 21, 2011, 05:07:32 ПП
Кросавцег, что тут скажешь! Медведа меняй. :P
Назва: Re: Оптимизация ABAP-а
Відправлено: err від Листопад 09, 2011, 12:24:15 ПП
БОЛЬШОЕ Спасибо за документ по оптимизации... Было очень познавательно почитать и почерпнуть мудрость.

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

Итак E9


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
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Листопад 09, 2011, 12:40:05 ПП
Цитата: err від Листопад 09, 2011, 12:24:15 ПП
БОЛЬШОЕ Спасибо за документ по оптимизации... Было очень познавательно почитать и почерпнуть мудрость.
Да не за что... заходите вносите предложения. Ваш пример проверим и добавим. Спасибо за замечания.

Цитата: err від Листопад 09, 2011, 12:24:15 ПП
Рисунок 11: INDEX-TBL-1.png
Рисунок 12: Index-Tree-1.png
Проверю...
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Листопад 15, 2011, 12:52:57 ДП
Цитата: err від Листопад 09, 2011, 12:24:15 ПП
Да, ещё почему то не отображаются картинки в скаченном файле Оптимизация ABAP v1-2.pdf
Рисунок 11: INDEX-TBL-1.png
Рисунок 12: Index-Tree-1.png
Причина в том, что при передаче в PDF я эти две диаграммы не преобразовал из Visio в картинку и поэтому при сборке файла в PDF ничего не попало. В общем скоро выложу чуть дополненную очередную подверсию 1.3 где это уже будет исправлено.
Назва: Re: Оптимизация ABAP-а
Відправлено: mulyukov_am від Липень 27, 2012, 06:33:53 ДП
Большое спасибо авторам статьи. Оочень полезно.
Назва: Re: Оптимизация ABAP-а
Відправлено: A. від Грудень 17, 2012, 02:20:38 ПП
Оптимизация ABAP v1-2.pdf, стр. 15, f6). Вопрос: зачем используется вторичная рабочая область *mseg в подзапросе?
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Грудень 17, 2012, 02:30:35 ПП
Цитата: A. від Грудень 17, 2012, 02:20:38 ПП
Оптимизация ABAP v1-2.pdf, стр. 15, f6). Вопрос: зачем используется вторичная рабочая область *mseg в подзапросе?
Это к Дмитрию вопрос  8)

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 ).
Назва: Re: Оптимизация ABAP-а
Відправлено: A. від Грудень 17, 2012, 02:42:04 ПП
стр. 18:
ЦитатаПримечание: В данном случае, при чтении данных в операторе READ TABLE не
использовалось расширение BINARY SEARCH, так как таблица lt_t006a не была объявлена
как сортированная, а для не сортированных данных, использовать такой поиск нельзя.
Более подробно о том, как идет выбор данных, из внутренних таблиц, рассмотрим в
части, где будет описаны способы объявления таких таблиц.
Как-то нечётко. Binary search как раз можно применять для таблиц, объявленных как standard, и для которых выполнена предварительная сортировка по нужным полям. Применение этого оператора для таблиц, объявленных как sorted, смысла не имеет, т.к. при указании полного ключа (либо выровненных по левому краю полей полного ключа) будет использоваться бинарный поиск, в противном случае - полный перебор, повлиять на него невозможно.
Назва: Re: Оптимизация ABAP-а
Відправлено: A. від Грудень 17, 2012, 02:55:49 ПП
стр. 19:
ЦитатаОбрабатываются все SAP блокировки, установленные в текущей программе по
значению формального параметра _SCOPE для соответствующих функций
блокирования, происходит снятие таких блокировок.
Снятие блокировок типа 1 и 3 не происходит после commit work, они снимаются только при выходе из программы либо с помощью DEQUEUE_<enq_obj> (DEQUEUE_ALL). Тип 3 ставит две блокировки - одну для модулей обновления вида V1, вторую - внутри программы, для локальных обновлений, например. Для типа 2 блокировка не снимается, если модуль обновления не вызван.
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Грудень 17, 2012, 05:35:59 ПП
Цитата: A. від Грудень 17, 2012, 02:20:38 ПП
Оптимизация ABAP v1-2.pdf, стр. 15, f6). Вопрос: зачем используется вторичная рабочая область *mseg в подзапросе?
Давно дело было... Выборка без подзапроса и последующим циклом по внутренней с выборкой SELECT SINGLE из MSEG (с удалением сторно) заняла больше времени, чем указанная конструкция (больше миллионов позиций mseg). Не рекомендую так делать, сторно по другому удаляется. На одном проекте только удалось такое увидеть.
Назва: Re: Оптимизация ABAP-а
Відправлено: A. від Грудень 17, 2012, 08:35:50 ПП
Цитата: Dmitriy від Грудень 17, 2012, 05:35:59 ППНе рекомендую так делать, сторно по другому удаляется. На одном проекте только удалось такое увидеть.
А какие будут рекомендации? Насколько я помню, для ММ в документе сторно заполняется ссылка на изначальный документ, а вот в изначальном соответствующей перекрёстной ссылки нет.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Грудень 17, 2012, 09:57:00 ПП
Цитата: A. від Грудень 17, 2012, 08:35:50 ПП
А какие будут рекомендации?
Ну вот это и была рекомендация, как быстро обработать такую ситуацию. Еще как вариант в экзите ловить операцию сторно и делать отметку в первичном документе. Для быстрого исключения сторнированных документов.
Назва: Re: Оптимизация ABAP-а
Відправлено: A. від Грудень 17, 2012, 10:02:05 ПП
А, я просто подумал, что прогресс двинулся ещё дальше :)
В одном из проектов была Z-табличка, если я всё правильно помню.

Ещё хотел бы сказать, что есть орфографические и пунктуационные ошибки в тексте. Не принципиально для смысла, но режет глаз. И шрифт ужасный - строчная наклонная "и" ненормальная :)
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Грудень 17, 2012, 10:34:30 ПП
Цитата: A. від Грудень 17, 2012, 08:35:50 ПП
Насколько я помню, для ММ в документе сторно заполняется ссылка на изначальный документ, а вот в изначальном соответствующей перекрёстной ссылки нет.
В MSEG, по индексу (номеру и год сторно) можно выбрать сторно изначальных.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Грудень 17, 2012, 11:26:22 ПП
Цитата: A. від Грудень 17, 2012, 10:02:05 ПП
Ещё хотел бы сказать, что есть орфографические и пунктуационные ошибки в тексте. Не принципиально для смысла, но режет глаз. И шрифт ужасный - строчная наклонная "и" ненормальная :)
Ну это конвертация так в PDF проходит с  И, хотя у меня показывает нормально, но у меня дебиан, так что вполне может быть под виндой чуток по другому выглядит. Ошибки, подправим, но лучше конечно или мне отдельно на почту или тут написать. Остальные замечания то же учтем... если не очень поздно  8)
Назва: Re: Оптимизация ABAP-а
Відправлено: A. від Грудень 18, 2012, 02:06:38 ПП
стр. 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) - аналогично.
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Грудень 18, 2012, 06:56:13 ПП
Цитата: Uukrul від Грудень 17, 2012, 02:30:35 ПП
Это к Дмитрию вопрос  8)

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 ).
Рекомендую измерить. Вопрос к пытливым умам и просто знающим людям.
  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: ограничивал годом и заводом                 
Назва: Re: Оптимизация ABAP-а
Відправлено: A. від Грудень 19, 2012, 03:50:20 ПП
Вопрос такой, идея подхода - если заменять for all entries на создание индекса по нужным полям, в условии where указывать диапазон значений для каждого поля от и до, предварительно определив их.

Кто-нибудь пробовал? Стоит того?
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Грудень 19, 2012, 04:10:43 ПП
Цитата: A. від Грудень 19, 2012, 03:50:20 ПП
Вопрос такой, идея подхода - если заменять for all entries на создание индекса по нужным полям
Вообще-то на сколько я знаю такой операции как for all entries в языке SQL нет, это расширение языка абап которое транслируется вроде как в подзапросы, поэтому построение индекса по любому должно ускорить выбор вроде как.
Назва: Re: Оптимизация ABAP-а
Відправлено: Dmitriy від Грудень 19, 2012, 04:49:27 ПП
Цитата: A. від Грудень 19, 2012, 03:50:20 ПП
Вопрос такой, идея подхода - если заменять for all entries на создание индекса по нужным полям, в условии where указывать диапазон значений для каждого поля от и до, предварительно определив их.

Кто-нибудь пробовал? Стоит того?
Предлагаю попробовать и измерить, как раз как 3-й вариант выборки, в дополнение к коду выше.
Кстати, где-то в теме (и в документе .pdf) есть рекомендации про доп. ограничения, по моему там, где объясняется почему в условии иногда невыгоден оператор "<>". Т.е. смысл в том, чтобы "попасть" в индексы, когда нет ключа или он не полон.
Индекс № 1:

MANDT
MATNR
WERKS
LGORT
BWART
SOBKZ

Индекс № 2:

SMBLN
SJAHR
SMBLP

Можно учесть сторно по виду движения BWART, если предварительно созданы (или считываются стандартные) настройки, тогда сразу же за 1 выборку в одну вн. таблицу можно взять и исходные и сторно и затем в цикле работать уже со внутренней, к которой можно, допустим, объявить несколько ключей (прямой-сторно) ... Где и как взять виды движений сторно к "прямым" толковые ММ-щики знают. ;)   
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Червень 17, 2013, 12:02:01 ПП
Для немного оживления тем, ну и как небольшой анонс из будущего, небольшая заметка: Копирование данных внутренних таблиц - 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, это кстати обычно по умолчанию так, но ваш базис может случайно и отключить эту возможность.
Назва: Re: Оптимизация ABAP-а
Відправлено: kernel від Червень 30, 2016, 06:43:46 ДП
Внесу свое дополнение по оптимизации j6 на стр. 17.
1. Использовать символьные ссылки
2. Таблицу lt_t006a объявить как хэш-таблицу с уникальным ключом msehi. И работать как с хэш-таблицей.
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. Есть удобная обертка для данной задачи http://abap4.ru/zapolnenie-spravochnyx-polej-tablicy-po-klyuchu.html
2. Похожая обертка, использующая INSERT REPORT https://habrahabr.ru/post/244615/
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Червень 30, 2016, 11:20:25 ДП
Цитата: kernel від Червень 30, 2016, 06:43:46 ДП
2. Таблицу lt_t006a объявить как хэш-таблицу с уникальным ключом msehi. И работать как с хэш-таблицей.
Вот тут не согласен, в этой таблице в общем случае будет ну пусть 20 единиц измерения, SAP для таких таблиц вообще не рекомендует использовать хэш-таблицы, так как накладные расходы на ведение B-дерева будут больше чем вообще просто фулсканом проходить эти 20 записей. Так что тут или цифры в студию или верим рекомендациям разработчика системы, который говорит что хэш-таблицы объявляйте для таблиц с большим количеством данных, а единицы измерения ну никак не попадают под этот критерий.
Назва: Re: Оптимизация ABAP-а
Відправлено: kernel від Липень 02, 2016, 09:00:17 ПП
В случае с ЕИ согласен, стандартная таблица работает незначительно быстрее. Но если заполнять, например, наименования материалов, то разница будет очень ощутима. Ниже результаты теста и листинг.

Всего записей в таблице - 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

Листинг

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+ строк лучший результат по времени давала хэш-таблица.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Липень 03, 2016, 01:26:47 ПП
Цитата: kernel від Липень 02, 2016, 09:00:17 ПП
Случай с ЕИ скорее исключение из правил. В моих отчетах, заказчик хочет видеть: наименования БЕ, заводов, групп материалов, материалов, складов, счетов, контрагентов, подразделений, и т.п. Во всех отчетах с 1000+ строк лучший результат по времени давала хэш-таблица.
Ну в этом списке к исключениям единиц измерения относятся перечисленные вами БЕ, Заводы, Группы ОЗМ, Склады, Счета и не относятся сами ОЗМ и Контрагенты, т..е. это как раз ОЗМ и контрагенты являются исключением в данном случае  8), ну а так конечно все правильно написали.
Назва: Re: Оптимизация ABAP-а
Відправлено: kernel від Липень 03, 2016, 05:37:35 ПП
Нет, именно ЕИ исключение из правил. Ниже тот же пример + поле завода в главной таблице.
На 52 уникальных заводах уже хэш-таблица дает лучший результат.
   8.040.207   Perform FILL_WERKS_TEST_STANDARD
   6.081.066   Perform FILL_WERKS_TEST_SORTED
   5.513.933   Perform FILL_WERKS_TEST_HASHED
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Серпень 16, 2016, 03:21:22 ПП
Так сказать еще немного оптимизации в тему, а именно чуток заметок по работе со строками в новых версиях системы от 7.40 и старше.

В самом начале существования языка ABAP, в системе был доступен единственный способ соединения строк, это оператор CONCATENATE. Простой процесс формирования строки в цикле, предполагал выделение достаточного места для строки приемника, и далее уже выполнялось формирование результата.

ВремВып: 810 микросек
6.5.1) Базовая операция соединения строк

DATA: l_long_char(10000) TYPE c,
      l_sy_index(10) TYPE c.

l_long_char = `Create long char, line = START`.
DO 100 TIMES.
  l_sy_index = sy-index.
  CONCATENATE l_long_char 'Create long char, line =' l_sy_index '.' INTO l_long_char.
ENDDO.
CONCATENATE l_long_char `Create long char, line = FINISH` INTO l_long_char.

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

ВремВып: 605 микросек
6.5.2) Прямая запись цепочки знаков в позицию строки

DATA: l_long_char(10000) TYPE c,
      l_sy_index(10)     TYPE c,
      l_add_char(100)    TYPE c.

l_long_char = `Create long char, line = START`.
DO 100 TIMES.
  l_sy_index = sy-index.
  CONCATENATE 'Create long char, line =' l_sy_index '.' INTO l_add_char.
  DATA(l_len) = strlen( l_long_char ).
  l_long_char+l_len = l_add_char.
ENDDO.
CONCATENATE l_long_char `Create long char, line = FINISH` INTO l_long_char.


Как видим прирост производительности для варианта 6.5.2 составляет 25%. Что в принципе неплохо, особенно если у вас в программе выполняется постоянная работа со строками. Кстати, на производительность в данном случае влияет размер строк с которыми выполняются операции.

В данный момент, в системе существуют новые операции сложения строк, которые являются с одной стороны, более быстрыми, а с другой более гибкими. Это операция соединения строк использующая операнд && и операция обработки шаблонов строк | |. Если сформировать аналогичный пример обработки строк, используя примеры переменных из задач 6.5.1 и 6.5.2, то производительность получится, где-то посредине, между операцией CONCATENATE и прямой записью строки в заданную позицию. В среднем пример 6.5.3 давал результат от 660 до 690 микросек. При этом обработки шаблонов всегда была чуть медленнее, чем операция соединения &&.

ВремВып: 685 микросек
6.5.3) Обработка шаблонов строк

DATA: l_long_char(10000) TYPE c,

l_long_char = `Create long char, line = START`.
DO 100 TIMES.
  l_long_char = |{ l_long_char }Create long char, line ={ sy-index }.|.
ENDDO.
l_long_char = l_long_char && 'Create long char, line = FINISH'.


ВремВып: 678 микросек
6.5.4) Соединение строк операцией &&

DATA: l_long_char(10000) TYPE c,

l_long_char = `Create long char, line = START`.
DO 100 TIMES.
  l_long_char = l_long_char && 'Create long char, line =' && sy-index && '.'.
ENDDO.
l_long_char = l_long_char && 'Create long char, line = FINISH'.

Из приятного, код примеров 6.5.3 и  6.5.4, выглядит менее перегруженным, а так же отсутствуют лишние переменные, так как нет ограничений на использование только определенных типов, как для оператора CONCATENATE. Но самое приятное это появление типа STRING, с которым оператор CONCATENATE работает, по моему мнению, очень плохо, а вот новые операторы работы со строками работают просто великолепно и быстро. Для примера перепишем пример 6.5.3 и 6.5.4 используя тип STRING.

ВремВып: 57 микросек
6.5.5) Обработка шаблонов строк для типа STRING

DATA: l_long_string TYPE string.

l_long_string = `Create long string, line = START`.
DO 100 TIMES.
  l_long_string = |{ l_long_string }Create long char, line ={ sy-index }.|.
ENDDO.
l_long_string = l_long_string && 'Create long char, line = FINISH'.


ВремВып: 50 микросек
6.5.6) Соединение строк операцией && для типа STRING

DATA: l_long_string TYPE string.

l_long_string = `Create long string, line = START`.
DO 100 TIMES.
  l_long_string = l_long_string && 'Create long char, line =' && sy-index && '.'.
ENDDO.
l_long_string = l_long_string && 'Create long char, line = FINISH'.

Как видим, скорость обработки,  отличается практически на порядок, т.е. более чем в 10 раз. Так же большим плюсом использования новых операторов является возможность, как указания различных типов переменных, так и вызова методов классов или выполнения каких-либо вычислений в процессе выполнения соединения данных. Например, выполнение вычисления значения переменной используя внутренние функции системы. В примере 6.5.7, используется возведение числа в степень.

ВремВып: 300 микросек
6.5.7) Соединение строк операцией && с динамическим вычислением значений

DATA: l_long_string TYPE string.

l_long_string = `Create long string, line = START`.
DO 100 TIMES.
  l_long_string = l_long_string && 'Create long char, line =' &&
                  CONV string( ipow( base = sy-index exp = 2 ) ) &&
                  '.'.
ENDDO.
l_long_string = l_long_string && 'Create long char, line = FINISH'.

Однако, стоит вынести вычисления из операции соединения строк, как скорость выполения резко возрастает, что видно на примере 6.5.8. При этом аналогичное правило так же работает и в случае обработки соединения строк используя шаблоны, т.е. время обработки для примера 6.5.8 меньше времени выполнения для примера 6.5.7, в пять раз.


ВремВып: 57 микросек
6.5.8) Соединение строк операцией && с вынесеним операций.

DATA: l_ipow type i,
      l_long_string TYPE string.

l_long_string = `Create long string, line = START`.
DO 100 TIMES.
  l_ipow = ipow( base = sy-index exp = 2 ).
  l_long_string = l_long_string && 'Create long char, line =' && l_ipow && '.'.
ENDDO.
l_long_string = l_long_string && 'Create long char, line = FINISH'.


Выводы (скорость): Где это возможно, лучше использовать тип переменной строка (STRING). Скорость обработки операции со строками, в системе, выше, чем с скорость обработки цепочек символов. Далее, не смотря на то, что новые операции соединения строк позволяют использовать динамическое вычисление значений в ходе вызова соединения строки, использовать данную возможность следует осторожно, так как оптимизации вызова таких вычислений не спросиходит и это существенно сказывается на скорости выполнения кода, что хорошо видно в примерах 6.5.7 и 6.5.8.
Назва: Re: Оптимизация ABAP-а
Відправлено: Uukrul від Квітень 06, 2019, 01:43:55 ДП
Ну что-то давно небыло ничего про оптимизацию, а как показывает практика, умелыми руками можно тормознуть все и никакая HANA DB вам не поможет  8) В общем надо было тут ускорить одну программу, функциональность FM (Бюджетирование), в одном месте был кусок кода, который к позиции заказа ММ выбирал данные контракта ММ и из заголовка и позиций дополнял данные. Так как до этого с CDS (Core Data Service) особо не имел, то пришлось поставить Eclipce (Отдельная песня, со своими припевами оказалось). Далее как-то по быстрому исходя из примеров того, что написано в системе, наваял CDS. Ну что сказать, даже мой кривой пример работает несколько быстрее чем OpenSQL. В среднем цифры выходят такие:

SQL:  2 441 083
CDS:  1 557 681

Программа, примеры запросов выкусил из оригинальной программы, после чего сделал CDS и вызвал его. Стандартно CDS видится как ракурс/view.

*&---------------------------------------------------------------------*
*& Report Z_TEST_SQL
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT z_test_sql.

DATA: time2     TYPE i,
      time1     TYPE i,
      time_diff TYPE i,

      time_sql  TYPE i,
      time_cds  TYPE i.

DATA: l_swap TYPE xfeld.

DATA: lt_line TYPE STANDARD TABLE OF ifmrepgax.

SELECT ebeln AS refbn,
       ebelp AS rfpos
INTO CORRESPONDING FIELDS OF TABLE @lt_line
FROM ekpo WHERE konnr <> @space.

l_swap = abap_true.
LOOP AT lt_line INTO DATA(ls_line).
  IF l_swap = abap_false.
    l_swap = abap_true.
    GET RUN TIME FIELD time1.

    SELECT SINGLE konnr,
                  ktpnr,
                  meins
    INTO (@ls_line-zz_ebeln, @ls_line-zz_ebelp, @ls_line-zz_meins)
    FROM ekpo
    WHERE ebeln = @ls_line-refbn AND
          ebelp = @ls_line-rfpos. " Сист.номер договору

    SELECT SINGLE ihrez,
                  kdatb,
                  kdate,
                  ktwrt,
                  waers,
                  matkl
    INTO (@ls_line-zz_ihrez, @ls_line-zz_kdatb, @ls_line-zz_kdate, @ls_line-zz_ktwrt, @ls_line-zz_waers, @ls_line-zz_cn_matkl)
    FROM ekko
    INNER JOIN ekpo ON ekko~ebeln = ekpo~ebeln
    WHERE ekko~ebeln = @ls_line-refbn AND
          ebelp = @ls_line-rfpos AND
          ekko~bstyp = 'K'.

    GET RUN TIME FIELD time2.
    time_diff = time2 - time1.
    time_sql = time_sql + time_diff.
  ELSE.
    l_swap = abap_false.
    GET RUN TIME FIELD time1.

    SELECT SINGLE ord_konnr AS zz_ebeln,
            ord_ktpnr AS zz_ebelp,
            ord_matkl AS zz_matkl,
            knt_ihrez AS zz_ihrez,
            knt_kdatb AS zz_kdatb,
            knt_kdate AS zz_kdate,
            knt_ktwrt AS zz_ktwrt,
            knt_waers AS zz_waers,
            knt_matkl AS zz_cn_matkl
    INTO (@ls_line-zz_ebeln, @ls_line-zz_ebelp, @ls_line-zz_matkl, @ls_line-zz_ihrez, @ls_line-zz_kdatb, @ls_line-zz_kdate, @ls_line-zz_ktwrt, @ls_line-zz_waers, @ls_line-zz_cn_matkl)
    FROM zekko_tv WHERE ebeln = @ls_line-refbn AND
                        ebelp = @ls_line-rfpos.

    GET RUN TIME FIELD time2.
    time_diff = time2 - time1.
    time_cds = time_cds + time_diff.
  ENDIF.
ENDLOOP.

WRITE: / 'SQL:', time_sql,
       / 'CDS:', time_cds.


CDS  выглядит как-то так, но даже при этом работает быстрее, а это еще процентов 70 производительности.

@AbapCatalog.sqlViewName: 'ZEKKO_TV'
@VDM.viewType: #BASIC
@EndUserText.label: 'Тестовий приклад'
define view ZUTN_EKKO_TEST as select from ekko as ek
inner join ekpo as ep on ep.ebeln = ek.ebeln
inner join ekko as kt on kt.ebeln = ep.konnr and kt.bstyp = 'K'
inner join ekpo as kp on kp.ebeln = kt.ebeln and kp.ebelp = ep.ktpnr
{
    key ek.ebeln as ebeln,
    key ep.ebelp as ebelp,
   
    ep.konnr as ord_konnr,
    ep.ktpnr as ord_ktpnr,
    ep.matkl as ord_matkl,
   
    kt.ihrez as knt_ihrez,
    kt.kdatb as knt_kdatb,
    kt.kdate as knt_kdate,
    kt.ktwrt as knt_ktwrt,
    kt.waers as knt_waers,
   
    kp.matkl as knt_matkl
}
where ek.bstyp = 'F'
group by  ek.ebeln,
          ep.ebelp,
   
          ep.konnr,
          ep.ktpnr,
          ep.matkl,
   
          kt.ihrez,
          kt.kdatb,
          kt.kdate,
          kt.ktwrt,
          kt.waers,
   
          kp.matkl