Найти в Дзене
SAP для фрилансера

ABAP для новичков - важность BINARY SEARCH

Когда вы начинаете кодить на ABAP, наверняка, не обращаете особого внимания на тип таблиц, который вы используете (STANDARD, SORTED, HASHED), и можете забыть использовать оператор дополнения BINARY SEARCH. Возможно, вы знаете, что использование этого дополнения повышает производительность. Для новичков довольно сложно понять, почему BINARY SEARCH оптимальнее. Я написал небольшой пример тестирования 4 случаев: Я подготовил переменные, смотрите ниже: TYPES: BEGIN OF lt_head, docnr TYPE n LENGTH 10, gjahr TYPE gjahr, END OF lt_head, BEGIN OF lt_position, docnr TYPE n LENGTH 10, gjahr TYPE gjahr, posnr TYPE n LENGTH 3, END OF lt_position. DATA: li_head TYPE STANDARD TABLE OF lt_head WITH HEADER LINE, li_positions TYPE STANDARD TABLE OF lt_position WITH HEADER LINE, li_positions_sorted TYPE SORTED TABLE OF lt_position WITH NON-UNIQUE KEY do

Когда вы начинаете кодить на ABAP, наверняка, не обращаете особого внимания на тип таблиц, который вы используете (STANDARD, SORTED, HASHED), и можете забыть использовать оператор дополнения BINARY SEARCH.

Возможно, вы знаете, что использование этого дополнения повышает производительность. Для новичков довольно сложно понять, почему BINARY SEARCH оптимальнее.

Я написал небольшой пример тестирования 4 случаев:

  • LOOP WHERE на STANDARD TABLE (отсортировано с помощью оператора sort)
  • LOOP WHERE на SORTED TABLE
  • READ TABLE BINARY SEARCH + LOOP FROM INDEX по STANDARD TABLE (отсортировано с помощью оператора sort)
  • ПРОЧИТАЙТЕ ТАБЛИЦУ BINARY SEARCH + LOOP FROM INDEX над SORTED TABLE

Я подготовил переменные, смотрите ниже:

TYPES: BEGIN OF lt_head,

docnr TYPE n LENGTH 10,

gjahr TYPE gjahr,

END OF lt_head,

BEGIN OF lt_position,

docnr TYPE n LENGTH 10,

gjahr TYPE gjahr,

posnr TYPE n LENGTH 3,

END OF lt_position.

DATA: li_head TYPE STANDARD TABLE OF lt_head

WITH HEADER LINE,

li_positions TYPE STANDARD TABLE OF lt_position

WITH HEADER LINE,

li_positions_sorted TYPE SORTED TABLE OF lt_position

WITH NON-UNIQUE KEY docnr gjahr posnr

WITH HEADER LINE.

LI_HEAD будет содержать 5000 записей и каждая из этих записей будет содержать 5 записей в таблицах LI_POSITIONS и LI_POSITIONS_SORTED, программа выполнит только циклы LOOP, без кода внутри, как показано ниже (Вы можете игнорировать макросы, которые я использовал для измерения времени выполнения):

START_MEASUREMENT 'SORT'.

SORT li_positions BY docnr gjahr posnr.

END_MEASUREMENT 'SORT'.

START_MEASUREMENT 'LOOP WHERE'.

LOOP AT li_head.

LOOP AT li_positions WHERE docnr = li_head-docnr

AND gjahr = li_head-gjahr.

ENDLOOP.

ENDLOOP.

END_MEASUREMENT 'LOOP WHERE'.

START_MEASUREMENT 'LOOP WHERE SORTED TABLE'.

LOOP AT li_head.

LOOP AT li_positions_sorted WHERE docnr = li_head-docnr

AND gjahr = li_head-gjahr.

ENDLOOP.

ENDLOOP.

END_MEASUREMENT 'LOOP WHERE SORTED TABLE'.

START_MEASUREMENT 'BINARY SEARCH'.

LOOP AT li_head.

READ TABLE li_positions WITH KEY docnr = li_head-docnr

gjahr = li_head-gjahr

BINARY SEARCH.

IF sy-subrc = 0.

LOOP AT li_positions FROM sy-tabix.

IF li_positions-docnr <> li_head-docnr OR

li_positions-gjahr <> li_head-gjahr.

EXIT.

ENDIF.

ENDLOOP.

ENDIF.

ENDLOOP.

END_MEASUREMENT 'BINARY SEARCH'.

START_MEASUREMENT 'BINARY SEARCH SORTED TABLE'.

LOOP AT li_head.

READ TABLE li_positions_sorted WITH KEY docnr = li_head-docnr

gjahr = li_head-gjahr

BINARY SEARCH.

IF sy-subrc = 0.

LOOP AT li_positions_sorted FROM sy-tabix.

IF li_positions_sorted-docnr <> li_head-docnr OR

li_positions_sorted-gjahr <> li_head-gjahr.

EXIT.

ENDIF.

ENDLOOP.

ENDIF.

ENDLOOP.

END_MEASUREMENT 'BINARY SEARCH SORTED TABLE'.

Выполнение программы дает следующие результаты:

-2

Как и ожидалось, LOOP WHERE дает худшую производительность, причина, по которой этот LOOP работает так плохо, - у ABAP недостаточно информации для выполнения оптимизации BINARY SEARCH.

Разница между первым и вторым LOOP, которая помогает ABAP оптимизировать поиск, заключается в том, что таблица позволяет узнать, что внутренняя таблица отсортирована. Также важно знать, что она отсортирована по соответствующим полям и ABAP знает это, потому что мы указали ключ в определении таблицы, как вы можете видеть в коде my LOOP, где условие использует поля ключа. Вы должны заметить, что, как в примере использование полного ключа не требуется для оптимизации.

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

Я также проверил, чтобы выполнить ручной BINARY SEARCH и начать цикл с этой позиции, пока не нашел другую комбинацию для своих ключевых полей. Это решение я обычно использовал, когда не понимал, как работает ABAP, я неожиданно обнаружил, что он работает немного лучше. Это будет полезно, если вам нужно выжать до последнего бита производительности.

Вы можете найти полный код в этом репозитории github: https://github.com/jordirosa/ABAP4Newbies