Привет!
Каждый ABAP разработчик знает несколько способов чтения внутренней таблицы. В то же время, не каждый знает как они соотносятся друг с другом по скорости работы.
В этой статье мы попробуем ответить на этот вопрос.
Как и предыдущий, этот тест, разумеется, не претендует на полноту, но может быть полезен практикующим разработчикам.
Исходные данные
Будем проводить тесты на 3-х типах таблиц:
- STANDARD
- SORTED
- HASHED
За основу возьмем структуру инфо-типа 0002 «Персональные данные» (из HCM модуля).
Длина структуры приведена ниже:
Существует большое количество всевозможных вариаций описания типа таблицы. Мы остановимся на следующих трех:
Объявим внутреннюю таблицу и заполним ее значениями из базы данных (БД):
В итоге, мы получили таблицу размером 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
Запустив отчет, получим следующий результат:
Как и следовало ожидать, из 1000 замеров времени первое место чаще всего занимал способ с ASSIGNING — 353 раза.
Однако, этот способ показал лишь 4 место по среднему времени выполнения 1000 операций — 0,0293589 сек.
Также, отчетливо видно, что более новые способы уступают в скорости классическому READ TABLE. Особенно при необходимости использования операторов TRY CATCH. Однако, как мы и условились выше, здесь мы сравниваем не «чистые» операции, а более приближенные к их реальному использованию.
SORTED TABLE
Для сортированной таблицы мы видим такое же распределение мест, но среднее время значительно улучшилось. Преимущество использования FIELD-SYMBOL’ов стало более очевидным.
HASHED TABLE
Хеш таблица повела себя странно. Результаты для нее оказались близки к результатам стандартной таблицы. Это не та скорость, которую мы искали…
По идее, чтение из хеш-таблицы должно происходить намного быстрее. Преимущество должно быть заметно даже для 1000 строк, например как здесь. Однако, этого не произошло. Если вы знаете почему, напишите пож-та в комментариях. Возможно, ошибка где-то между монитором и креслом…
Выводы
Что ж, Америку мы не открыли, но какие-то выводы все-же сделаем.
- Если вам важна скорость, каждая микросекунда на счету, используйте классический READ TABLE. Лучше всего использовать его в паре с FIELD-SYMBOL’ами (ASSIGNING).
- В целом, в первую очередь обращайте внимание на тип таблицы. Если таблица средних размеров, используйте SORTED TABLE.
- Если классика вам надоела и хочется работать с Table Expressions, выберите самый быстрый вариант — с присвоением FIELD-SYMBOL’а.
Подписывайтесь на Telegram канал.
Пока!