Привет!

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

В этой статье мы попробуем ответить на этот вопрос.

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

Исходные данные

Будем проводить тесты на 3-х типах таблиц:

  1. STANDARD
  2. SORTED
  3. HASHED

За основу возьмем структуру инфо-типа 0002 «Персональные данные» (из HCM модуля).

Длина структуры приведена ниже:

Длина таблицы PA0002

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

Объявим внутреннюю таблицу и заполним ее значениями из базы данных (БД):

В итоге, мы получили таблицу размером 2,5 Мб:

Требования и ограничения

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

Таким образом мы постараемся приблизиться к тому, как используют те или иные способы при решении реальных задач.

В то же время, не будем слишком углубляться в бизнес-логику и специфику модуля SAP HCM, и искать смысл в том, как именно мы читаем данные инфо-типа.

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

Тестируемые способы

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

1 READ TABLE mt_itab INTO ls_itab WITH KEY fieldname = … .

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

2 READ TABLE mt_itab ASSIGNING <ls_itab> WITH KEY fieldname = … .

Чтение внутренней таблицы с присвоением символа поля (field symbol) найденной записи. Чуть менее популярный способ (опять же, по моему опыту).

3 READ TABLE mt_itab REFERENCE INTO lr_itab WITH KEY fieldname = … .

В случае успешного чтения в переменной lr_itab будет содержаться ссылка на найденную строку таблицы. Для получения доступа к содержимому необходимо будет выполнить разыменовывание ( ->*).

4 ls_itab = VALUE ty_itab( mt_itab[ fieldname = … ] OPTIONAL ).

Способ чтения внутренней таблицы с помощью табличных выражений (ABAP Table Expressions). Оборачивание операции в VALUE …( …OPTIONAL) необходимо для того, чтобы избежать дампа если запись не найдена.

5 ASSIGN mt_itab[ fieldname = … ] TO <ls_itab>.

Еще один вариант использования табличных выражений. В случае успешного выполнения будет присвоен field symbol <ls_itab> на найденную строку.

6 TRY. ls_itab = mt_itab[ fieldname = … ]. CATCH cx_… . ENDTRY.

В отличии от 4-го способа, здесь мы явно отлавливаем исключение CX_SY_ITAB_LINE_NOT_FOUN с помощью TRY CATCH.

7 TRY. lr_itab = REF ty_itab( mt_itab[ fieldname = … ] ). CATCH cx_… . ENDTRY.

Последний в нашем списке вариант. В случае успешного выполнения в lr_itab будет ссылка на найденную строку. Как и в варианте 3 для получения доступа к содержимому необходимо будет выполнить разыменовывание ( ->*). Для того, чтобы поймать исключение CX_SY_ITAB_LINE_NOT_FOUN оборачиваем все в TRY CATCH.

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

Методика тестирования

Для того, чтобы не сравнивать микросекунды и их доли, будем замерять время выполнения не 1, а 1000 операций чтения внутренней таблицы, размером 1000 строк.

Сделаем 1000 таких замеров и рассчитаем среднее время выполнения 1000 операций чтения. Также, посмотрим сколько раз тот или иной способ занимал 1-е, 2-е и т.д. места.

Пишем код

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

Анализируем результаты

Начнем с теста стандартной таблицы.

STANDARD TABLE

Запустив отчет, получим следующий результат:

Результат работы отчета, STANDARD TABLE

Как и следовало ожидать, из 1000 замеров времени первое место чаще всего занимал способ с ASSIGNING — 353 раза.

Однако, этот способ показал лишь 4 место по среднему времени выполнения 1000 операций — 0,0293589 сек.

Также, отчетливо видно, что более новые способы уступают в скорости классическому READ TABLE. Особенно при необходимости использования операторов TRY CATCH. Однако, как мы и условились выше, здесь мы сравниваем не «чистые» операции, а более приближенные к их реальному использованию.

SORTED TABLE

Результат работы отчета, SORTED TABLE

Для сортированной таблицы мы видим такое же распределение мест, но среднее время значительно улучшилось. Преимущество использования FIELD-SYMBOL’ов стало более очевидным.

HASHED TABLE

Результат работы отчета, HASHED TABLE

Хеш таблица повела себя странно. Результаты для нее оказались близки к результатам стандартной таблицы. Это не та скорость, которую мы искали…

По идее, чтение из хеш-таблицы должно происходить намного быстрее. Преимущество должно быть заметно даже для 1000 строк, например как здесь. Однако, этого не произошло. Если вы знаете почему, напишите пож-та в комментариях. Возможно, ошибка где-то между монитором и креслом…

Выводы

Что ж, Америку мы не открыли, но какие-то выводы все-же сделаем.

  1. Если вам важна скорость, каждая микросекунда на счету, используйте классический READ TABLE. Лучше всего использовать его в паре с FIELD-SYMBOL’ами (ASSIGNING).
  2. В целом, в первую очередь обращайте внимание на тип таблицы. Если таблица средних размеров, используйте SORTED TABLE.
  3. Если классика вам надоела и хочется работать с Table Expressions, выберите самый быстрый вариант — с присвоением FIELD-SYMBOL’а.

Подписывайтесь на Telegram канал.

Пока!

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.