In SAP, for better performance, instead of using nested loops, we can use the index looping technique.
The following sample code explains the usage of index looping and shows the difference between nested loops and index looping:
*&--------------------------------------------------------------------&* *& Program Description: &* *& ----------------------- &* *& This demo program will demonstrate the use of index looping. &* *& &* *& &* *& Author: ABAPCOOKBOOK &* *& Website: www.abapcookbook.com &* ************************************************************************ REPORT ZDEMOINDEXLOOPING. *Internal tables and structures: DATA: lt_bkpf TYPE STANDARD TABLE OF bkpf, lt_bseg TYPE STANDARD TABLE OF bseg, lst_bkpf TYPE bkpf, lst_bseg TYPE bseg. *Variables: DATA: gv_stime TYPE i, \"Start Time gv_etime TYPE i, \"End Time gv_tdiff TYPE i, \"Time Difference gv_counter TYPE i, \"Record Counter gv_tabix TYPE sy-tabix. \"Tabix Position *------------------------------------* *DUMMY RETRIEVAL: * *------------------------------------* *Dummy retrieval for demo purposes. *Data at header level. SELECT * FROM bkpf INTO TABLE lt_bkpf UP TO 10 ROWS. IF sy-subrc EQ 0. * Sort and delete adjacent duplicates not necessary as * we are sorting and deleting by primary keys. However, we * will leave like that to remember that its a best practice * to sort and delete adjacents duplicates when using for * all entries. SORT lt_bkpf BY bukrs belnr gjahr. DELETE ADJACENT DUPLICATES FROM lt_bkpf COMPARING bukrs belnr gjahr. ENDIF. *If the table is not empty, proceed. Please note that *this is necessary when doing for all entries because *if the table \'LT_BKPF\' is empty, the following retrieval *will retrieve all the entries from table BSEG. IF lt_bkpf[] IS NOT INITIAL. * Data at item level. SELECT * FROM bseg INTO TABLE lt_bseg FOR ALL ENTRIES IN lt_bkpf WHERE bukrs EQ lt_bkpf-bukrs AND belnr EQ lt_bkpf-belnr AND gjahr EQ lt_bkpf-gjahr. IF sy-subrc EQ 0. * Sorting not required but its just for * information purposes. SORT lt_bseg BY bukrs belnr gjahr. ENDIF. ENDIF. *------------------------------------* *NESTED LOOPS: * *------------------------------------* *Get the starting time. GET RUN TIME FIELD gv_stime. *Nested Loops: *Loop at header level. LOOP AT lt_bkpf INTO lst_bkpf. * Loop at item level. LOOP AT lt_bseg INTO lst_bseg WHERE bukrs EQ lst_bkpf-bukrs AND belnr EQ lst_bkpf-belnr AND gjahr EQ lst_bkpf-gjahr. * Do some processing. gv_counter = gv_counter + 1. ENDLOOP. ENDLOOP. *Get the ending time. GET RUN TIME FIELD gv_etime. *Get the time difference, which will be the execution time *the code was executed. gv_tdiff = gv_etime - gv_stime. *Output the time difference. WRITE:/1(61) sy-uline. WRITE: /1 sy-vline, 2(40) \'Taking Taken Using Nested Loops:\', gv_tdiff, 41 sy-vline, 50(10) gv_tdiff, 61 sy-vline. *------------------------------------* *INDEX LOOPING: * *------------------------------------* CLEAR: gv_counter. *Get the starting time. GET RUN TIME FIELD gv_stime. *Nested Loops: *Loop at header level. LOOP AT lt_bkpf INTO lst_bkpf. * We will check if we have the header record * at item level. READ TABLE lt_bseg TRANSPORTING NO FIELDS WITH KEY bukrs = lst_bkpf-bukrs belnr = lst_bkpf-belnr gjahr = lst_bkpf-gjahr BINARY SEARCH. * If we have a match, get the tabix position * at which we found the header level record in * the item level table. IF sy-subrc EQ 0. * Get the tabix position of the line found * in \'LT_BSEG\'. The tabix position will be * used to start the next loop at that position. gv_tabix = sy-tabix. * Loop at item level. * Here, we will start looping in the table \'LT_BSEG\' * using the tabix position found above. LOOP AT lt_bseg INTO lst_bseg FROM gv_tabix. * Here, we will check if the current item level * record still match the header level record. If not, * means that we can exit the loop and take the next * header level record. IF lst_bkpf-bukrs NE lst_bseg-bukrs OR lst_bkpf-belnr NE lst_bseg-belnr OR lst_bkpf-gjahr NE lst_bseg-gjahr. * Clearing necessary items. CLEAR: gv_tabix, lst_bseg. * Okay, go out of the loop. EXIT. ENDIF. * If the IF statement above has failed, means that * that line at header level matches the line at item * level, do some processing. * Do some processing. gv_counter = gv_counter + 1. * Clearing necessary items. CLEAR: lst_bseg. ENDLOOP. ENDIF. * Clearing necessary items. CLEAR: lst_bkpf. ENDLOOP. *Get the ending time. GET RUN TIME FIELD gv_etime. *Get the time difference, which will be the execution time *the code was executed. gv_tdiff = gv_etime - gv_stime. *Output the time difference. WRITE:/1(61) sy-uline. WRITE: /1 sy-vline, 2(40) \'Taking Taken Using Index Looping:\', gv_tdiff, 41 sy-vline, 50(10) gv_tdiff, 61 sy-vline. WRITE:/1(61) sy-uline.
The results clearly shows that index looping is much better than nested loops.