LP21 / RLLNACH1 performance
Overview
We use LP21 / RLLNACH1 (WM replenishment for fixed bins) in background processing. We have defined background jobs with 3-6 steps which executes RLLNACH1 for different storage types and storage locations. Execution times for biggest storage location were between 45 and 90 minutes. The job is scheduled 6 times every day, which gives total execution time from 4,5 to 7 hours! Every job execution creates 100 – 150 transfer orders, so it should not last so long.
Problem cause
I checked source code and debug the program – it was not performing any long SELECT statements, but the most of the time spends in READ_MATERIAL_NEW_46 form.
I found instructions (RLLNACH1, lines 1461-1471):
LOOP AT inspl.
LOOP AT p_mard
WHERE matnr = inspl-matnr
AND werks = werks
AND lgort = inspl-lgort.
EXIT.
ENDLOOP.
IF sy-subrc <> 0.
DELETE inspl.
ENDIF.
ENDLOOP.
In our case tables p_mard and inspl contain:
– p_mard[] – 511000 rows
– inspl[] – 59000 rows
When we check definition of P_MARD table:
DATA: BEGIN OF P_MARD OCCURS 100.
INCLUDE STRUCTURE MARD.
DATA: END OF P_MARD.
it appears to be a standard table.
It is obvious, that searching this table with simple LOOP is very inefficient.
Solution
I created a modification:
*{ REPLACE 1
*\ LOOP AT inspl.
*\ LOOP AT p_mard
*\ WHERE matnr = inspl-matnr
*\ AND werks = werks
*\ AND lgort = inspl-lgort.
*\ EXIT.
*\ ENDLOOP.
*\ IF sy-subrc <> 0.
*\ DELETE inspl.
*\ ENDIF.
*\ ENDLOOP.
*** RLLNACH1 performance
SORT p_mard[] BY matnr werks lgort.
LOOP AT inspl.
READ TABLE p_mard[]
TRANSPORTING NO FIELDS
WITH KEY matnr = inspl-matnr
werks = werks
lgort = inspl-lgort
BINARY SEARCH.
IF sy-subrc <> 0.
DELETE inspl.
ENDIF.
ENDLOOP.
*** RLLNACH1 performance - end
*} REPLACE
Test results
Results of this change was very satisfactory.
Here are execution times before and after change:
– 5 days before
– 5 days after
– 6 executions every day
execution times | before [s] | after [s] | after / before |
MIN | 2750 | 103 | 3,7% |
MAX | 5088 | 216 | 4,2% |
AVG | 3441 | 164 | 4,8% |
As a result of the change described here, program execution time descreased over 25 times.
I'd've chosen a different route though - one that doesn't change the program data.
data: lto_zzz_mard like sorted table of p_mard with non-unique key matnr werks lgort.
insert lines of p_mard into table lto_zzz_mard.
LOOP AT inspl.
READ TABLE lto_zzz_mard
TRANSPORTING NO FIELDS
WITH TABLE KEY matnr = inspl-matnr
werks = werks
lgort = inspl-lgort.
IF sy-subrc <> 0.
DELETE inspl.
ENDIF.
ENDLOOP.
clear lto_zzz_mard.
If you know that p_mard contains only unique records (with respect to matnr, werks, lgort), you can define a HASHED table, that could be even faster.
good point - I just informed SAP support.
You are right - with hashed table it could be even faster. There is also no need to use SELECT * - only key fields are used.
I tried to modify only small piece of code - results were very good, but as You see - there are more lines, that could be changed.
Regards,
--
Przemysław
Thanks for good analysis. I am a Basis Consultant. I would like to know which functional uses this program. Can you please tell the use of this code so that I can also check whether it can be used in my client.
Thanks,
Ranjith.
Thank You for first comment 🙂
This is WM functionality (WM replenishment for fixed bins) to create transfer orders between different storage types - check who is privileged to use LP21 or if You have the program scheduled in background.
Regards,
--
Przemysław