In previous post Parallel Cursor – To speed up performance of Nested LOOP, we have seen a technique how to speed up the performance of the nested LOOP constructs in ABAP. In today’s post, we will see another variance of the Parallel cursor technique. In this technique, we will exit out the inner LOOP when both keys are not matching by saving the LOOP index in a variable. This index variable would be used in the LOOP construct to start the LOOP. Initially, this index variable would be set to 1. Statistics shows that this new technique is powerful over the technique as shown in the previous post which uses the READ TABLE.
Here is the code snippet to achieve this Parallel Cursor technique:
*&---------------------------------------------------------------------*
*& Report ZTEST_NP_PARALLEL_CURSOR
*& Purpose: Illustration on how to use Parallel Cursor
*&---------------------------------------------------------------------*
*
REPORT ztest_np_parallel_cursor.
*
TYPES: ty_t_vbak TYPE STANDARD TABLE OF vbak.
DATA: it_vbak TYPE ty_t_vbak .
*
TYPES: ty_t_vbap TYPE STANDARD TABLE OF vbap.
DATA: it_vbap TYPE ty_t_vbap.
*
FIELD-SYMBOLS: <lfs_vbak> LIKE LINE OF it_vbak,
<lfs_vbap> LIKE LINE OF it_vbap.
*
* necessary data selection
SELECT * FROM vbak
INTO TABLE it_vbak
UP TO 100 ROWS.
CHECK it_vbak IS NOT INITIAL.
SELECT * FROM vbap
INTO TABLE it_vbap
FOR ALL ENTRIES IN it_vbak
WHERE vbeln = it_vbak-vbeln.
*
DATA: lv_start_time TYPE timestampl,
lv_end_time TYPE timestampl,
lv_diff TYPE timestampl.
DATA: lv_tabix TYPE i.
*
*....... Parallel Cursor with Nested Loop .......................
* Get the Start Time
GET TIME STAMP FIELD lv_start_time.
*
* Starting the Parallel Cursor
SORT: it_vbak BY vbeln,
it_vbap BY vbeln.
LOOP AT it_vbak ASSIGNING <lfs_vbak>.
*
* Read the second internal table with BINARY SEARCH
READ TABLE it_vbap TRANSPORTING NO FIELDS
WITH KEY vbeln = <lfs_vbak>-vbeln
BINARY SEARCH.
* Get the TABIX number
lv_tabix = sy-tabix.
* Start the LOOP from the first accessed record in
* previous READ i.e. LV_TABIX
LOOP AT it_vbap FROM lv_tabix ASSIGNING <lfs_vbap> .
*
* End the LOOP, when there is no more record with similar key
IF <lfs_vbap>-vbeln <> <lfs_vbak>-vbeln.
EXIT.
ENDIF.
* Rest of the logic would go from here...
*
ENDLOOP.
*
ENDLOOP.
*
* Get the end time
GET TIME STAMP FIELD lv_end_time.
*
* Actual time Spent:
lv_diff = lv_end_time - lv_start_time.
WRITE: /(50) 'Time Spent on Parallel Cursor Nested loops:', lv_diff.
CLEAR: lv_start_time, lv_end_time, lv_diff.
*
*....... Parallel Cursor - 2 with Nested Loop ...................
CLEAR lv_tabix.
* Get the Start Time
GET TIME STAMP FIELD lv_start_time.
*
* Starting the Parallel Cursor
SORT: it_vbak BY vbeln,
it_vbap BY vbeln.
lv_tabix = 1. " Set the starting index 1
LOOP AT it_vbak ASSIGNING <lfs_vbak>.
*
* Start the nested LOOP from the index
LOOP AT it_vbap FROM lv_tabix
ASSIGNING <lfs_vbap>.
* Save index & Exit the loop, if the keys are not same
IF <lfs_vbak>-vbeln <> <lfs_vbap>-vbeln.
lv_tabix = sy-tabix.
EXIT.
ENDIF.
* Rest of the logic would go from here...
*
ENDLOOP.
ENDLOOP.
*
* Get the end time
GET TIME STAMP FIELD lv_end_time.
*
* Actual time Spent:
lv_diff = lv_end_time - lv_start_time.
WRITE: /(50) 'Time Spent on Parallel Cursor 2 Nested loops', lv_diff.
CLEAR: lv_start_time, lv_end_time, lv_diff.
This statistics and graph shows the time used by the nested LOOP as the 100%. For the 1000 VBAK records, parallel cursor technique with READ consumes 1.84% time compare to nested LOOPs 100%. This technique without READ TABLE only requires 1.05% time compare to 100% of nested LOOPs.
Great performance demonstration!
But you're cheating a little bit: The sort is measured on the first loop, but not on the second. To be "correct", the sort must be done outside of both testing-loops. :}
Hello Enno,
But you're cheating a little bit: The sort is measured on the first loop, but not on the second. To be "correct", the sort must be done outside of both testing-loops. :}
This much little bit cheating is okay, as long as it demonstrates the purpose. 🙂
Regards,
Naimesh Patel
Hi Nameish!
I think that both options are great, but it depends of the context because the second option isn't apply when the it_vbak table don't contains the primary key of the it_vbak table.
CDGR
PD: great blog!!
Hi Nameish.
Your program give me a lot inspiration. I also have some problem when I use this code. so I made some improvement. hope it help for anybody.
——————————-
LOOP AT it_vbak ASSIGNING .
LOOP AT it_vbap FROM lv_tabix
ASSIGNING .
IF -vbeln < -vbeln.
lv_tabix = sy-tabix.
EXIT.
ELSEIF -vbeln = -vbeln.
* Rest of the logic would go from here…
ELSE.
ENDIF.
ENDLOOP.
ENDLOOP.
LOOP AT it_vbak ASSIGNING lfs_vbak.
LOOP AT it_vbap FROM lv_tabix ASSIGNING lfs_vbap.
IF lfs_vbak-vbeln < lfs_vbap-vbeln.
lv_tabix = sy-tabix.
EXIT.
ELSEIF lfs_vbak-vbeln = lfs_vbap-vbeln.
* Rest of the logic would go from here…
ELSE.
* nothing here
ENDIF.
ENDLOOP.
ENDLOOP.
Hello Stanley,
Thanks for the improvement.
I am working on to have code lines with field-symbols.
Regards,
Naimesh Patel