본문 바로가기
ABAP/개발Tip

[개발Tip] Internal Table 성능(Select into, Read, Loop where) 비교

by name_text 2023. 5. 16.

Internal Table 성능(Select into, Read, Loop where) 비교

Standard Table, Sorted Table, Hashed Table

 

SAP Internal Table에 대한 설명과 각 유형별 성능 비교 자료는 구글링을 하면 무수히 많이 나오며, Easy ABAP에도 상세시 설명이 되어 있습니다.

 

다만, 대부분의 사이트에서 Internal Table 성능 비교에 대해 Append와 Read Table에서만 얘기하고 있어서

문득 Select into와 Standard Table에서 다른 유형의 Move시 그리고 Loop where에서의 성능이 얼마나 차이가 나는지 궁금해서 테스트를 해봤습니다.

단, Binary Search가 아닌 Standard table의 Read가 느리다는건 다들 알고 있으므로 비교에서는 생략했습니다.

 

#1. Internal Table 성능 비교 (100만건 테이터 기준)

시뮬레이션을 많이 해본것은 아니다보니 절대적인 성능 비교표는 아닙니다, '이정도 차이가 나는구나~' 하고 참고만 해주세요.

1만건, 5만건 같이 비교적 적은 데이터로 테스트 했을때는 Select into시 각 유형별 차이가 별로 없었습니다.

Internal Table별 성능 비교표(데이터 100만건 기준)

#2. 나름의 결론

Unique Key, Non Unique Key 모두 사용할수 있고, 대부분의 상황에서 준수한 성능을 내는 Sorted Table이 저에게는 최고인듯 싶습니다.

 

#3. 테스트 소스코드

REPORT YTEMP_SANDBOX.
INCLUDE ZCM_PROGRESS.
  TYPES: BEGIN OF T_ITAB,
    KEY1(20) TYPE C,
    END OF T_ITAB.

  DATA: LT_ITAB1 TYPE STANDARD TABLE OF T_ITAB,
        LS_ITAB1 LIKE LINE OF LT_ITAB1,

        LT_ITAB2 TYPE SORTED TABLE OF T_ITAB WITH UNIQUE KEY KEY1,
        LS_ITAB2 LIKE LINE OF LT_ITAB2,

        LT_ITAB3 TYPE HASHED TABLE OF T_ITAB WITH UNIQUE KEY KEY1,
        LS_ITAB3 LIKE LINE OF LT_ITAB3,

        LT_TEMP TYPE STANDARD TABLE OF T_ITAB,
        LS_TEMP LIKE LINE OF LT_TEMP,

        LV_STRING TYPE STRING,
        LV_KEY1  LIKE LS_ITAB1-KEY1,
        LV_TABIX TYPE SY-TABIX.
  DATA: LV_RINDEX TYPE DATATYPE-INTEGER4.
  DATA: LV_RTIME TYPE I.

  PARAMETERS P_COUNT LIKE G_PROGRESS_TOTAL OBLIGATORY DEFAULT 1000000.

START-OF-SELECTION.

  CLEAR : LT_ITAB1[], LT_ITAB2[], LT_ITAB3[], LT_TEMP[].

  PERFORM INITIAL_PROGRESS_VARIANT.
  G_PROGRESS_TOTAL = P_COUNT.
  DO G_PROGRESS_TOTAL TIMES.
    CALL FUNCTION 'GENERAL_GET_RANDOM_STRING'
      EXPORTING
        NUMBER_CHARS        = 5
      IMPORTING
        RANDOM_STRING       = LV_STRING
              .
    MOVE: LV_STRING TO LS_TEMP-KEY1. CONDENSE LS_TEMP-KEY1.
    LS_TEMP-KEY1 = LS_TEMP-KEY1 && SY-TABIX.
    APPEND LS_TEMP TO LT_TEMP.

    PERFORM SET_PROGRESS_WITH_PERCENT USING 'Gen random string'.
  ENDDO.


  PERFORM INITIAL_PROGRESS_VARIANT.
  G_PROGRESS_TOTAL = 12.
* select into 시간 비교
  DATA: LT_BKPF_T TYPE STANDARD TABLE OF BKPF,
        LT_BKPF_S TYPE SORTED TABLE OF BKPF WITH UNIQUE KEY MANDT BUKRS GJAHR BELNR,
        LT_BKPF_H TYPE HASHED TABLE OF BKPF WITH UNIQUE KEY MANDT BUKRS GJAHR BELNR.
  "STANDARD TABLE
  PERFORM SET_PROGRESS_WITH_STEP USING 'Select-into Time - Standard Table'.
  GET RUN TIME FIELD LV_RTIME.
  SELECT
    BUKRS, GJAHR, BELNR
  FROM BKPF
  INTO CORRESPONDING FIELDS OF TABLE @LT_BKPF_T
    UP TO @P_COUNT ROWS
    BYPASSING BUFFER.
  IF SY-SUBRC EQ 0.
    SORT LT_BKPF_T BY BUKRS GJAHR BELNR.
  ENDIF.
  PERFORM DETERMINE_WRITE USING 'Standard Table Select-Into' LV_RTIME.

  PERFORM SET_PROGRESS_WITH_STEP USING 'Select-into Time - Sorted Table'.
  GET RUN TIME FIELD LV_RTIME.
  SELECT
    BUKRS, GJAHR, BELNR
  FROM BKPF
  INTO CORRESPONDING FIELDS OF TABLE @LT_BKPF_S
    UP TO @P_COUNT ROWS
    BYPASSING BUFFER.
  PERFORM DETERMINE_WRITE USING 'Sorted Table Select-Into' LV_RTIME.

  PERFORM SET_PROGRESS_WITH_STEP USING 'Select-into Time - Hashed Table'.
  GET RUN TIME FIELD LV_RTIME.
  SELECT
    BUKRS, GJAHR, BELNR
  FROM BKPF
  INTO CORRESPONDING FIELDS OF TABLE @LT_BKPF_H
    UP TO @P_COUNT ROWS
    BYPASSING BUFFER.
  PERFORM DETERMINE_WRITE USING 'Hashed Table Select-Into' LV_RTIME.


* APPEND 시간 비교
  "STANDARD TABLE
  PERFORM SET_PROGRESS_WITH_STEP USING 'Data Move Time - Standard Table'.
  GET RUN TIME FIELD LV_RTIME.
  LT_ITAB1 = CORRESPONDING #( LT_TEMP[] ).
  SORT LT_ITAB1 BY KEY1.
  PERFORM DETERMINE_WRITE USING 'Standard Table Data Move' LV_RTIME.

  "SORTED TABLE
  PERFORM SET_PROGRESS_WITH_STEP USING 'Data Move Time - Sorted Table'.
  GET RUN TIME FIELD LV_RTIME.
  LT_ITAB2 = CORRESPONDING #( LT_TEMP[] ).
  PERFORM DETERMINE_WRITE USING 'Sorted Table Data Move' LV_RTIME.

  "HASHED TABLE
  PERFORM SET_PROGRESS_WITH_STEP USING 'Data Move Time - Hashed Table'.
  GET RUN TIME FIELD LV_RTIME.
  LT_ITAB3 = CORRESPONDING #( LT_TEMP[] ).
  PERFORM DETERMINE_WRITE USING 'Hashed Table Data Move'
                                LV_RTIME.

* READ TABLE 성능 비교
  DATA(LV_TLINE) = LINES( LT_TEMP ).
  "STANDARD TABLE BINARY SEARCH
  PERFORM SET_PROGRESS_WITH_STEP USING 'Read Time - Binary Search'.
  GET RUN TIME FIELD LV_RTIME.
  DO LV_TLINE TIMES.
    CALL FUNCTION 'RANDOM_I4'
      EXPORTING
        RND_MIN         = 1
        RND_MAX         = LV_TLINE
      IMPORTING
        RND_VALUE       = LV_RINDEX
              .
    READ TABLE LT_TEMP INTO LS_TEMP INDEX LV_RINDEX.
    IF SY-SUBRC EQ 0.
      READ TABLE LT_ITAB1 INTO LS_ITAB1 WITH KEY KEY1 = LS_TEMP-KEY1 BINARY SEARCH.
    ENDIF.
  ENDDO.
  PERFORM DETERMINE_WRITE USING 'Binary Search'
                                LV_RTIME.

  "SORTED TABLE
  PERFORM SET_PROGRESS_WITH_STEP USING 'Read Time - Sorted Search'.
  GET RUN TIME FIELD LV_RTIME.
  DO LV_TLINE TIMES.
    CALL FUNCTION 'RANDOM_I4'
      EXPORTING
        RND_MIN         = 1
        RND_MAX         = LV_TLINE
      IMPORTING
        RND_VALUE       = LV_RINDEX
              .
    READ TABLE LT_TEMP INTO LS_TEMP INDEX LV_RINDEX.
    IF SY-SUBRC EQ 0.
      READ TABLE LT_ITAB2 INTO LS_ITAB2 WITH TABLE KEY KEY1 = LS_TEMP-KEY1.
    ENDIF.
  ENDDO.
  PERFORM DETERMINE_WRITE USING 'Sorted Search'
                                LV_RTIME.

  "HASHED TABLE
  PERFORM SET_PROGRESS_WITH_STEP USING 'Read Time - Hashed Search'.
  GET RUN TIME FIELD LV_RTIME.
  DO LV_TLINE TIMES.
    CALL FUNCTION 'RANDOM_I4'
      EXPORTING
        RND_MIN         = 1
        RND_MAX         = LV_TLINE
      IMPORTING
        RND_VALUE       = LV_RINDEX
              .
    READ TABLE LT_TEMP INTO LS_TEMP INDEX LV_RINDEX.
    IF SY-SUBRC EQ 0.
      READ TABLE LT_ITAB3 INTO LS_ITAB3 WITH TABLE KEY KEY1 = LS_TEMP-KEY1.
    ENDIF.
  ENDDO.
  PERFORM DETERMINE_WRITE USING 'Hashed Search'
                                LV_RTIME.


* Loop 성능 비교
  "STANDARD TABLE LOOP - 실행 시간이 너무 오래 걸려서 주석처리
*  PERFORM SET_PROGRESS_WITH_STEP USING 'Loop Time - Standard'.
*  GET RUN TIME FIELD LV_RTIME.
*  DO LV_TLINE TIMES.
*    CALL FUNCTION 'RANDOM_I4'
*      EXPORTING
*        RND_MIN         = 1
*        RND_MAX         = LV_TLINE
*      IMPORTING
*        RND_VALUE       = LV_RINDEX
*              .
*    READ TABLE LT_TEMP INTO LS_TEMP INDEX LV_RINDEX.
*    IF SY-SUBRC EQ 0.
*      LOOP AT LT_ITAB1 INTO LS_ITAB1 WHERE KEY1 EQ LS_TEMP-KEY1.
*
*      ENDLOOP.
*    ENDIF.
*  ENDDO.
*  PERFORM DETERMINE_WRITE USING 'Standard Loop'
*                                LV_RTIME.

  "SORTED TABLE LOOP
  PERFORM SET_PROGRESS_WITH_STEP USING 'Loop Time - Sorted'.
  GET RUN TIME FIELD LV_RTIME.
  DO LV_TLINE TIMES.
    CALL FUNCTION 'RANDOM_I4'
      EXPORTING
        RND_MIN         = 1
        RND_MAX         = LV_TLINE
      IMPORTING
        RND_VALUE       = LV_RINDEX
              .
    READ TABLE LT_TEMP INTO LS_TEMP INDEX LV_RINDEX.
    IF SY-SUBRC EQ 0.
      LOOP AT LT_ITAB2 INTO LS_ITAB2 WHERE KEY1 EQ LS_TEMP-KEY1.

      ENDLOOP.
    ENDIF.
  ENDDO.
  PERFORM DETERMINE_WRITE USING 'Sorted Loop'
                                LV_RTIME.

  "HASHED TABLE LOOP
  PERFORM SET_PROGRESS_WITH_STEP USING 'Loop Time - Hashed'.
  GET RUN TIME FIELD LV_RTIME.
  DO LV_TLINE TIMES.
    CALL FUNCTION 'RANDOM_I4'
      EXPORTING
        RND_MIN         = 1
        RND_MAX         = LV_TLINE
      IMPORTING
        RND_VALUE       = LV_RINDEX
              .
    READ TABLE LT_TEMP INTO LS_TEMP INDEX LV_RINDEX.
    IF SY-SUBRC EQ 0.
      LOOP AT LT_ITAB3 INTO LS_ITAB3 WHERE KEY1 EQ LS_TEMP-KEY1.

      ENDLOOP.
    ENDIF.
  ENDDO.
  PERFORM DETERMINE_WRITE USING 'Hashed Loop'
                                LV_RTIME.
*&---------------------------------------------------------------------*
*& Form DETERMINE_WRITE
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> P_
*&      --> LV_SDATE
*&      --> LV_STIME
*&---------------------------------------------------------------------*
FORM DETERMINE_WRITE  USING    PV_TEXT
                               PV_RTIME.
  DATA: LV_RTIME TYPE I,
        LV_FTIME TYPE I.
  GET RUN TIME FIELD LV_RTIME.
  LV_FTIME = LV_RTIME - PV_RTIME.
  WRITE :/ PV_TEXT,' : ', LV_FTIME, 'MicroSecond'.
ENDFORM.

 

댓글