加速ABAP中的长运行循环



在分析SAP导出脚本(SAP R/3,4.06b)中的性能问题时,我发现以下代码在测试系统中运行约10分钟。在生产中可能会快一点,但我不能在那里测试。

LOOP AT ZMARD.
  LOOP AT ZCOMB.
       IF ZCOMB-MATNR = ZMARD-MATNR.
          IF ZCOMB-LGORT = ZMARD-LGORT.
           IF ZCOMB-IND = ' '.
             IF ZCOMB-PLUMI = '+'.
                ZMARD-LABST = ZMARD-LABST + ZCOMB-MNG01.
             ELSEIF ZCOMB-PLUMI = '-'.
                ZMARD-LABST = ZMARD-LABST - ZCOMB-MNG01.
             ENDIF.                          "PLUMI
          ENDIF.                             "IND
        ENDIF.                               "LGORT
      ENDIF.                                 "MATNR
  ENDLOOP.
  IF ZMARD-LABST < 0.
     ZMARD-LABST = 0.
  ENDIF.
  WRITE ZMARD-LABST DECIMALS 0 TO ZMARD-ZLABST.
  MODIFY ZMARD.
ENDLOOP.

关于如何将这些循环优化/组合成一个循环,你有什么建议吗?

你好,肯定有一些可能性。

首先:您可以用"where outer looped struct field"="inner loop table field"来限制内部循环。

第二:你可以使用哈希表。但这些对于阅读表来说更为重要。

这是两个表需要相交的经典情况。示例中的代码是最糟糕的方法之一,并且可以得到显著改进。这是一篇有趣的文章。

下面是为您的示例实现的。

假设:1.ZMARD对于MATNR LGORT组合没有重复条目;2.ZMARD的顺序对报告不重要;

DATA: IX_MARD TYPE I,
      IX_COMB TYPE I.
DEFINE READ_NEXT.
  ADD 1 TO IX_&1.
  READ TABLE Z&1 INDEX IX_&1.
  IF SY-SUBRC NE 0.
    IX_&1 = -1.
  ENDIF.
END-OF-DEFINITION.
" It would be better if these sorts were done
" in the SELECT of the data
SORT ZMARD BY MATNR LGORT.
SORT ZCOMB BY MATNR LGORT.
IX_MARD = IX_COMB = 0.
READ_NEXT: MARD, COMB.
WHILE IX_MARD GT 0 AND IX_COMB GT 0.
  IF ZMARD-MATNR EQ ZCOMB-MATNR AND
     ZMARD-LGORT EQ ZCOMB-LGORT.
    " Match between MARD and COMB
    IF ZCOMB-IND = ' '.
      IF ZCOMB-PLUMI = '+'.
         ZMARD-LABST = ZMARD-LABST + ZCOMB-MNG01.
      ELSEIF ZCOMB-PLUMI = '-'.
         ZMARD-LABST = ZMARD-LABST - ZCOMB-MNG01.
      ENDIF.                          "PLUMI
    ENDIF.                             "IND
    READ_NEXT: COMB.
  ELSEIF ZMARD-MATNR LT ZCOMB-MATNR OR
         ( ZMARD-MATNR EQ ZCOMB-MATNR AND
           ZMARD-LGORT LT ZCOMB-LGORT
         ).
    " MARD behind COMB
    IF ZMARD-LABST < 0.
       ZMARD-LABST = 0.
    ENDIF.
    WRITE ZMARD-LABST DECIMALS 0 TO ZMARD-ZLABST.
    MODIFY ZMARD INDEX IX_MARD.
    READ_NEXT MARD.
  ELSE.
    " MARD ahead of COMB
    READ_NEXT COMB.
  ENDIF. " Match on material and storage location
ENDWHILE.
WHILE IX_MARD GT 0.
  IF ZMARD-LABST < 0.
     ZMARD-LABST = 0.
  ENDIF.
  WRITE ZMARD-LABST DECIMALS 0 TO ZMARD-ZLABST.
  MODIFY ZMARD INDEX IX_MARD.
  READ_NEXT MARD.
ENDWHILE.

请注意,我刚刚在这里编辑了这段代码,所以我预计它会有一些语法错误和bug。

我认为应该过滤内部循环。此外,我会将这些表定义为SORTED表(WITH NON-SORTED KEY),至少是"ZCOMB",键为MATNR、LGORT,可能还有IND.

我也会使用sy-tabix变量来保持行的位置,然后像这样使用它:

MODIFY ZMARD INDEX lv_tabix.

或者我可以使用字段符号。这是你的决定。

代码如下所示:

DATA lv_index type sy-tabix.
LOOP AT ZMARD.
  lv_index = sy-tabix.
  LOOP AT ZCOMB WHERE MATNR = ZMARD-MATNR AND LGORT = ZMARD-LGORT AND IND = ' '.
             IF ZCOMB-PLUMI = '+'.
                ZMARD-LABST = ZMARD-LABST + ZCOMB-MNG01.
             ELSEIF ZCOMB-PLUMI = '-'.
                ZMARD-LABST = ZMARD-LABST - ZCOMB-MNG01.
             ENDIF.                          "PLUMI
  ENDLOOP.
  IF ZMARD-LABST < 0.
     ZMARD-LABST = 0.
  ENDIF.
  WRITE ZMARD-LABST DECIMALS 0 TO ZMARD-ZLABST.
  MODIFY ZMARD INDEX lv_index.
ENDLOOP.

最后,在我看来,另一种方法是在"ZCOMB"上循环,并使用COLLECT对数据求和,然后用这些求和修改"ZMARD",用二进制搜索读取表。

在我看来,这可以提高性能,因为你只需要在一个表上循环。

希望能有所帮助。

这段代码似乎想为ZMARD中的所有条目更新ZMARD-LABST。在表循环中对表进行循环似乎真的很慢。如果您在MATNR上对ZMARD进行排序,那么您可以在两个不同的循环中进行排序。类似的东西

DATA lv_tabix type sy-tabix.
FIELD-SYMBOLS <MARD> like ZMARD. "I dont know the type of ZMARD
SORT ZCOMB BY MATNR.    
LOOP AT ZCOMB.
  IF ZCOMB-IND NE ' '.
    CONTINUE.
  ENDIF.
  IF <MARD>-MATNR NE ZCOMB-MATNR OR <MARD>-LGORT NE ZCOMB-LGORT. 
    "This could be a binary read, because of sorting we only do a read per material
    READ TABLE MARD ASSIGNING <MARD> WITH KEY MATNR = ZCOMB-MATNR LGORT = ZCOMB-LGORT.
    IF SY-SUBRC NE 0.
      CONTINUE.
    ENDIF.
  ENDIF.
  IF ZCOMB-PLUMI = '+'.
    ADD ZCOMB-MNG01 TO <MARD>-LABST.
  ELSEIF ZCOMB-PLUMI = '-'.
    SUBTRACT ZCOMB-MNG01 FROM <MARD>-LABST.
  ENDIF.
ENDLOOP.

LOOP AT ZMARD.
  lv_index = sy-tabix.
  IF ZMARD-LABST < 0.
     ZMARD-LABST = 0.
  ENDIF.
  WRITE ZMARD-LABST DECIMALS 0 TO ZMARD-ZLABST.
  MODIFY ZMARD INDEX lv_tabix.
ENDLOOP.

请注意,MARD有3个键:MATNR、BUKRS和LGORT。我希望你的LGORT值不会与WERKS交叉,或者ZCOMB有一个你可以使用的WERKS字段。

如果你不关心执行顺序,你可以这样做(未经测试):

SORT ZMARD BY MATNR LGORT.
SORT ZCOMB BY MATNR LGORT.
LOOP AT ZMARD ASSIGNING <ZMARD>.
READ TABLE ZCOMB WITH KEY
                MATNR = <ZMARD>-MATNR
                LGORT = <ZMARD>-LGORT
                TRANSPORTING NO FIELDS.
IF sy-subrc = 0.                            
    lv_index = sy-tabix.
ELSE.
    CONTINUE.
ENDIF.
LOOP AT ZCOMB ASSIGNING <ZCOMB> FROM lv_index.
    IF <ZCOMB>-MATNR <> <ZMARD>-MATNR OR <ZCOMB>-LGORT <> <ZMARD>-LGORT.
        EXIT.
    ENDIF.
    IF <ZCOMB>-IND = ' '.
        IF <ZCOMB>-PLUMI = '+'.
            <ZMARD>-LABST = <ZMARD>-LABST + <ZCOMB>-MNG01.
        ELSEIF ZCOMB-PLUMI = '-'.
            <ZMARD>-LABST = <ZMARD>-LABST - <ZCOMB>-MNG01.
        ENDIF.
    ENDIF.
ENDLOOP. " ZCOMB loop

ENDLOOP。"ZMARD循环

相关内容

  • 没有找到相关文章

最新更新