1

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.

このループを最適化して 1 つのループにまとめる方法について何かアドバイスはありますか?

4

5 に答える 5

2

これは、2 つのテーブルを交差させる必要がある典型的なケースです。あなたの例のコードは、それを行う最悪の方法の 1 つであり、劇的に改善することができます。これについて興味深い記事があります。

そして、これがあなたの例のために実装されたものです。

前提: 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.

ここでこのコードを編集したばかりなので、構文エラーやバグが含まれることが予想されます。

于 2015-06-23T21:20:23.623 に答える
2

内側のループをフィルタリングする必要があると思います。さらに、テーブルを SORTED テーブル (WITH NON-SORTED KEY)、少なくともキー MATNR、LGORT、およびおそらく IND を持つ「ZCOMB」として定義します。

また、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」を変更して BINARY SEARCH でテーブルを読み取ることです。

私の意見では、1 つのテーブルのみをループするため、パフォーマンスが向上する可能性があります。

それが役に立てば幸い。

于 2015-06-23T15:57:40.763 に答える
1

このコードはZMARD-LABST、ZMARD のすべてのエントリを更新しようとしているようです。テーブルループ内でテーブルをループすると、それを行うのが非常に遅いようです。ZMARD を MATNR でソートした場合、これを 2 つの異なるループで実行できます。何かのようなもの

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 には、MATNR、BUKRS、および LGORT の 3 つのキーがあることに注意してください。LGORT 値が WERKS を超えないか、ZCOMB に使用できる WERKS フィールドがあることを願っています。

于 2015-06-23T17:04:35.260 に答える
0

実行順序を気にしない場合は、これを行うことができます(テストされていません):

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

エンドループ。"ZMARD ループ

于 2015-06-27T15:07:21.843 に答える