Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

Very Large Select Option - - Tip

Former Member
0 Likes
748

I was performance tuning a ABAP program that had a very large select option criteria. It had a combination of Include equal and Include equal ranges. So first, I tried this logic:

IF P_SPLIT IS INITIAL.
 P_SPLIT = 1.
ENDIF.

DESCRIBE Table S_VBELV LINES NUM_LINES.
NUM_REC = NUM_LINES DIV P_SPLIT.
**
**
CLEAR   IT_VBFA.
REFRESH IT_VBFA.
**
DO P_SPLIT TIMES.

 wk_num = sy-index.

 CASE WK_NUM.
  When 1.
   FROM_INDEX = 1.
   TO_INDEX = NUM_REC.
  When P_SPLIT.
   FROM_INDEX = TO_INDEX + 1.
   TO_INDEX = NUM_LINES.
  When Others.
   FROM_INDEX = TO_INDEX + 1.
   TO_INDEX = FROM_INDEX + ( NUM_REC - 1 ).
 ENDCASE.

 CASE sy-index.
   When 1.
    Refresh  R_VBELV01.
    append lines of S_VBELV FROM FROM_INDEX TO TO_INDEX to R_VBELV01.
    SELECT VBELN
      FROM VBFA
       APPENDING TABLE IT_VBFA
        WHERE VBELV in R_VBELV01
         %_hints oracle 'INDEX ( "&TABLE&" "VBFA~0" "VBFA^0" )'.
   When 2.
    Refresh  R_VBELV02.
    append lines of S_VBELV FROM FROM_INDEX TO TO_INDEX to R_VBELV02.
    SELECT VBELN
      FROM VBFA
       APPENDING TABLE IT_VBFA
        WHERE VBELV in R_VBELV02
         %_hints oracle 'INDEX ( "&TABLE&" "VBFA~0" "VBFA^0" )'.
   When 3.
    Refresh  R_VBELV03.
    append lines of S_VBELV FROM FROM_INDEX TO TO_INDEX to R_VBELV03.
    SELECT VBELN
      FROM VBFA
       APPENDING TABLE IT_VBFA
        WHERE VBELV in R_VBELV03
         %_hints oracle 'INDEX ( "&TABLE&" "VBFA~0" "VBFA^0" )'.
   When 4.
    Refresh  R_VBELV04.
    append lines of S_VBELV FROM FROM_INDEX TO TO_INDEX to R_VBELV04.
    SELECT VBELN
      FROM VBFA
       APPENDING TABLE IT_VBFA
        WHERE VBELV in R_VBELV04
         %_hints oracle 'INDEX ( "&TABLE&" "VBFA~0" "VBFA^0" )'.
   When 5.
    Refresh  R_VBELV05.
    append lines of S_VBELV FROM FROM_INDEX TO TO_INDEX to R_VBELV05.
    SELECT VBELN
      FROM VBFA
       APPENDING TABLE IT_VBFA
        WHERE VBELV in R_VBELV05
         %_hints oracle 'INDEX ( "&TABLE&" "VBFA~0" "VBFA^0" )'.
 ENDCASE.

ENDDO. 

What my testing revealed is that when I split the selection up into 5 ranges the program was much faster than before this logic - - actually it was timing out when using the actual select option values. Then I ran it spliting up the selection in 4 ranges and the program ran longer. Then into 3 ranges which yielded a longer run time than when run with 4. Using 2 ranges was even slower, and with only 1 range the program would time out. Even with these improvements, I still was not happy. So I wrote code to read the Select Option, remember everything was equal value and built a Internal Table containing just the "Low" values. This meant, there was a range, code was needed to convert the range into individual lines. For example, "I" "BT" "0090204305" "0090204308" resulted in the internal table containing entries" "0090204305", "0090204306", "0090204307", and "0090204308". I then changed the select to

     SELECT VBELN
      FROM VBFA
       INTO TABLE IT_VBFA
        WHERE VBELV IN S_VBELV
          %_hints oracle 'INDEX ( "&TABLE&" "VBFA~0" "VBFA^0" )'.
 

The performance gained was amazing. Conclusion is that if you have a program that someone could contain a very large bucket of Select option values, convert the values into a internal table and use "For All Entries" as shown above.

Hope this helps.

I was performance tuning a ABAP program that had a very large select option criteria. It had a combination of Include equal and Include equal ranges. So first, I tried this logic:

IF P_SPLIT IS INITIAL.
 P_SPLIT = 1.
ENDIF.

DESCRIBE Table S_VBELV LINES NUM_LINES.
NUM_REC = NUM_LINES DIV P_SPLIT.
**
**
CLEAR   IT_VBFA.
REFRESH IT_VBFA.
**
DO P_SPLIT TIMES.

 wk_num = sy-index.

 CASE WK_NUM.
  When 1.
   FROM_INDEX = 1.
   TO_INDEX = NUM_REC.
  When P_SPLIT.
   FROM_INDEX = TO_INDEX + 1.
   TO_INDEX = NUM_LINES.
  When Others.
   FROM_INDEX = TO_INDEX + 1.
   TO_INDEX = FROM_INDEX + ( NUM_REC - 1 ).
 ENDCASE.

 CASE sy-index.
   When 1.
    Refresh  R_VBELV01.
    append lines of S_VBELV FROM FROM_INDEX TO TO_INDEX to R_VBELV01.
    SELECT VBELN
      FROM VBFA
       APPENDING TABLE IT_VBFA
        WHERE VBELV in R_VBELV01
         %_hints oracle 'INDEX ( "&TABLE&" "VBFA~0" "VBFA^0" )'.
   When 2.
    Refresh  R_VBELV02.
    append lines of S_VBELV FROM FROM_INDEX TO TO_INDEX to R_VBELV02.
    SELECT VBELN
      FROM VBFA
       APPENDING TABLE IT_VBFA
        WHERE VBELV in R_VBELV02
         %_hints oracle 'INDEX ( "&TABLE&" "VBFA~0" "VBFA^0" )'.
   When 3.
    Refresh  R_VBELV03.
    append lines of S_VBELV FROM FROM_INDEX TO TO_INDEX to R_VBELV03.
    SELECT VBELN
      FROM VBFA
       APPENDING TABLE IT_VBFA
        WHERE VBELV in R_VBELV03
         %_hints oracle 'INDEX ( "&TABLE&" "VBFA~0" "VBFA^0" )'.
   When 4.
    Refresh  R_VBELV04.
    append lines of S_VBELV FROM FROM_INDEX TO TO_INDEX to R_VBELV04.
    SELECT VBELN
      FROM VBFA
       APPENDING TABLE IT_VBFA
        WHERE VBELV in R_VBELV04
         %_hints oracle 'INDEX ( "&TABLE&" "VBFA~0" "VBFA^0" )'.
   When 5.
    Refresh  R_VBELV05.
    append lines of S_VBELV FROM FROM_INDEX TO TO_INDEX to R_VBELV05.
    SELECT VBELN
      FROM VBFA
       APPENDING TABLE IT_VBFA
        WHERE VBELV in R_VBELV05
         %_hints oracle 'INDEX ( "&TABLE&" "VBFA~0" "VBFA^0" )'.
 ENDCASE.

ENDDO. 

What my testing revealed is that when I split the selection up into 5 ranges the program was much faster than before this logic - - actually it was timing out when using the actual select option values. Then I ran it spliting up the selection in 4 ranges and the program ran longer. Then into 3 ranges which yielded a longer run time than when run with 4. Using 2 ranges was even slower, and with only 1 range the program would time out. Even with these improvements, I still was not happy. So I wrote code to read the Select Option, remember everything was equal value and built a Internal Table containing just the "Low" values. This meant, there was a range, code was needed to convert the range into individual lines. For example, "I" "BT" "0090204305" "0090204308" resulted in the internal table containing entries" "0090204305", "0090204306", "0090204307", and "0090204308". I then changed the select to

     SELECT VBELN
      FROM VBFA
       INTO TABLE IT_VBFA
        WHERE VBELV IN S_VBELV
          %_hints oracle 'INDEX ( "&TABLE&" "VBFA~0" "VBFA^0" )'.
 

The performance gained was amazing. Conclusion is that if you have a program that someone could contain a very large bucket of Select option values, convert the values into a internal table and use "For All Entries" as shown above.

Hope this helps.

2 REPLIES 2
Read only

alejandro_bindi
Active Contributor
0 Likes
654

Thanks for posting this tip, may come in handy.

I haven't had such a problem but knew it could occur, because every select option when executed must be translated to, for example OR, NOT, BETWEEN standard SQL conditional statements.

So if the SO content is large, there's a lot of overhead in performing that translation.

Regards.

Read only

Former Member
0 Likes
654

One warning - with some OS / Database there is a limit imposed on the total size of the actual SQL command that can be sent in a single request - this used to be 6K to 8K bytes in 31H systems.

So if your ranges table was too big, the select returned a short dump.

New DB versions / 64 bit architecture have probably improved this - don't know what the limit is in latest systems, or even if there is a limit.

Andrew