Performance-Problem

Getting started ... Alles für einen gelungenen Start.
71 Beiträge • Vorherige Seite 4 von 5 (current) Nächste
71 Beiträge Vorherige Seite 4 von 5 (current) Nächste

Re: Performance-Problem

Beitrag von DeathAndPain (Top Expert / 1964 / 261 / 415 ) »
Und obendrein schöner, weil es sich klarer und ansprechender liest zu schreiben

PROGRESS_INDICATOR 'Daten werden gelesen...'.

anstatt

STATISCHKLASSE=>PROGRESS_INDICATOR( 'Daten werden gelesen...' ).
D&P: Jetzt ist das Coding zwar überarbeitet - aber man sieht, dass du es auf die Schnelle gemacht hast. Was rausgekommen ist, ist ein typisches Beispiel für unleserliches Coding.
Das sehe ich deutlich anders und bin von meinem neuen Coding durchaus überzeugt.
Du willst eine Prozentzahl ermitteln. Da kann man doch nicht mit 99 multiplizieren und nachher noch +1 rechnen, damit komische Symptome dann korrigiert werden. Die Prozentzahl die du haben willst ist immer! 100 * sy-tabix / GES.
Das habe ich auch gedacht, als ich damals den Code erstellt habe. Aber es stimmt eben nicht, und genau deshalb habe ich den Code jetzt so geändert, dass es stimmt! Der minimale Wert, den die Uhr anzeigen kann, ist eben nicht 0%, sondern 1% (weil er bei 0 gar keine Uhr anzeigt). Dieser FB stellt mir also nicht 100 Schritte zur Verfügung, sondern nur 99, beginnend mit 1! Also muss ich die Laufzeit meines LOOP eben nicht in 100, sondern in 99 Teile aufteilen. Das ist die Einteilung, die mir der FB nur bietet. Ich brauche also gar keine Pro"cent", sondern Pro"neunundneunzig"! Damit ist das, was ich da mache, mathematisch absolut richtig und konsequent. Und als Ergebnis dieser Konsequenz fällt die Erfordernis der IF-Krücke weg. (Der Name des "PERCENTAGE"-Parameters des FB ist insofern irreführend.)

Wenn die SAP-Uhr nur sieben unterschiedliche Schritte anbieten würde, dann würde ich durch 7 teilen und nicht sagen, ich muss aber Prozente nehmen, also teile ich trotzdem durch 100 und baue hinterher irgendwelche Krücken ein, damit das dennoch vernünftig angezeigt wird.
Gewissermaßen macht das tatsächlich 5% Schritte - aber nur nachdem man sich durch das Coding gequält hat und die ganze >-Zeichenarie auswertet .
Quälen? Wenn ich Dich nicht kennen würde, dann würde ich jetzt fragen, ob Du ernsthaft ein Problem hast, ein Coding zu verstehen, das gerade mal aus 7 Zeilen besteht (zudem einfachen Zeilen, also nix mit verschachtelten Methoden und FOR und bla). Mein Fokus hier lag klar auf kurzem, performanten Code. Das Coding nachvollziehen soll gar niemand; wie es zu verwenden ist, steht ja im Kommentar oben drin (und wer es dennoch nachvollziehen möchte, der muss einem siebenzeiligen Code gewachsen sein).

Im dem Zusammenhang @Ralf: Das Makro soll gar nicht debuggt werden! Es ist die Idee hinter einem Makro, wie ein atomarer Befehl verwendet zu werden, und selbstverständlich sollte nichts, was innerhalb des Makros passiert, irgendwie mit dem Rest des Programmcodes in unerwarteter Weise interagieren können. Diese Bedingungen sind hier gegeben (jedenfalls solange man nicht auf die Idee kommt, die Variablen I, AI und GES woanders zu verwenden, aber das muss einem klar sein, wenn man dieses Makro per INCLUDE einbindet (steht ja deutlich im Kommentartext des Makros)).

gesponsert
Stellenangebote auf ABAPforum.com schalten
kostenfrei für Ausbildungsberufe und Werksstudenten


Re: Performance-Problem

Beitrag von cuncon (Specialist / 143 / 98 / 1 ) »
Hallo zusammen,

ich bin immer noch bei dem Performance-Probleme von diesem Programm. Nachdem ich das Programm korrigiert habe, so dass je 1000. Durchlauf der 2. Schleife nur ein mal FUBA SAPGUI_PROGRESS_INDICATOR aufgerufen werden soll, ist das Programm nicht mehr stehen geblieben, aber ein Timeout Fehler ist aufgetreten nach 20 Minuten. Danach habe ich Befehl commit work eingebaut, obwohl ich nur interne Tabelle modifiziert habe und kein transparente Tabelle , dann gab es kein timeout mehr und nach fast 40 Minute habe ich Ergebnis bekommen. Ich verstehe nicht so gut über commit work. Ich habe einfach nur probiert, weil ich irgendwo gelesen habe, dass um timeout Problem zu vermeiden, kann man commit work benutzen, aber dann mögen Administratoren nicht so gern und ich verstehe den Grund nicht, warum sie nicht mögen. Muss man vorsichtig sein, um commit work zu benutzen? Ihr sieht den Befehl COMMIT WORK ganz unten von der Coding, bevor ENDLOOP. Kann ich commit work bei meinem Programm verwenden? Unten ist mein Coding:

Code: Alles auswählen.

  LOOP AT  gt_output ASSIGNING <gs_output>.
    output_idx = sy-tabix.
*Lesen Warengruppenbezeichnung
    IF NOT <gs_output>-matkl IS INITIAL.
      SELECT SINGLE *
            INTO gs_t023t
            FROM T023T
            WHERE spras = 'DE'
              AND matkl = <gs_output>-matkl.
      IF sy-subrc = 0.
        <gs_output>-wgbez = gs_t023t-wgbez.
      ENDIF.
    ENDIF.
*Lesen Disponentenbezeichnung
    IF NOT <gs_output>-dispo IS INITIAL.
      SELECT SINGLE *
            INTO gs_t024d
            FROM T024D
            WHERE werks = '1000'
              AND dispo = <gs_output>-dispo.
      IF sy-subrc = 0.
        <gs_output>-dsnam = gs_t024d-dsnam.
      ENDIF.
    ENDIF.
*Lesen Positionstypenpruppe
    IF NOT <gs_output>-matnr IS INITIAL.
      SELECT SINGLE *
            INTO gs_mvke
            FROM mvke
            WHERE matnr = <gs_output>-matnr
              AND vkorg = '1000'
              AND vtweg = '10'.
      IF sy-subrc = 0.
        <gs_output>-mtpos = gs_mvke-mtpos.
      ENDIF.

      CONCATENATE 'Lesen der Bedarfs-/Bestandsliste bei matnr' <gs_output>-matnr INTO gv_text SEPARATED BY space.
      CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
       EXPORTING
*     PERCENTAGE       = 0
         TEXT             = gv_text
                .
      CLEAR gt_bestandliste. REFRESH gt_bestandliste.
*Lesen der Bedarfs-/Bestandsliste
      CALL FUNCTION 'MD_STOCK_REQUIREMENTS_LIST_API'
        EXPORTING
*       PLSCN                          =
          MATNR                          = <gs_output>-matnr
          WERKS                          = '1000'
*       BERID                          =
*       ERGBZ                          =
*       AFIBZ                          =
*       INPER                          =
*       DISPLAY_LIST_MDPSX             =
*       DISPLAY_LIST_MDEZX             =
*       DISPLAY_LIST_MDSUX             =
*       NOBUF                          =
*       PLAUF                          =
     IMPORTING
*       E_MT61D                        =
          E_MDKP                         = gs_mdkp
*       E_CM61M                        =
*       E_MDSTA                        =
*       E_ERGBZ                        =
       TABLES
*       MDPSX                          =
         MDEZX                          = gt_bestandliste
*       MDSUX                          =
       EXCEPTIONS
         MATERIAL_PLANT_NOT_FOUND       = 1
         PLANT_NOT_FOUND                = 2
         OTHERS                         = 3
                .
      IF SY-SUBRC <> 0.
        MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
                WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
      ELSE.
        gs_output-hoebe = gs_mdkp-hoebe.
        CLEAR gs_mdkp.

        SORT gt_bestandliste BY delb0 DESCENDING.
        DELETE gt_bestandliste WHERE delb0 = 'AR-RES'.
        gt_bestandliste_temp[] = gt_bestandliste[].

        LOOP AT gt_bestandliste ASSIGNING <gs_bestandliste>  WHERE delb0 = 'W-BEST' OR delb0 = 'KD-BST' OR delb0 = 'K-AUFT' OR delb0 = 'LIEFER' OR delb0 = 'SK-BED'.
          best_idx = sy-tabix.
          best_idx_n = best_idx.
          best_idx_1000 = best_idx mod 1000.
          if best_idx_1000 = 0.
            CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
             EXPORTING
*             PERCENTAGE       = 0
               TEXT             = best_idx_n
                      .
          endif.

*W-BEST = Werkbestand. Hier wird die verfügbare Menge von Werkbestand gelesen
          IF <gs_bestandliste>-delb0 = 'W-BEST'.
            gs_output-wbmng02 = <gs_bestandliste>-mng02.
          ENDIF.
*KD-BST = Kundeneinzelbestand. Hier wird die Summe der Kundeneinzelnebestände gelesen
          IF <gs_bestandliste>-delb0 = 'KD-BST'.
            <gs_output>-sum_kb = <gs_output>-sum_kb + <gs_bestandliste>-mng02.
*Kennzeichen"X" setzen,wenn mindestens ein negativer Kundenauftragsbestand vorliegt
            IF <gs_bestandliste>-mng02 < 0.
              <gs_output>-nkbflag = 'X'.
            ENDIF.
            "Kennzeichen "X" setzen, wenn Kundenauftragsbestände ohne Vorgang existieren, dh, wenn mng01 <> 0 und nächste Eintrag ist auch KD-BST und hat nicht gleiche planr
            IF <gs_bestandliste>-mng01 <> 0.
              IF <gs_output>-ovflag IS INITIAL.
                i = best_idx + 1.
                READ TABLE gt_bestandliste_temp INDEX i INTO gs_bestandliste_temp.
                IF sy-subrc = 0.
                  IF gs_bestandliste_temp-planr <> <gs_bestandliste>-planr.
                    <gs_output>-ovflag = 'X'.
                  ENDIF.
                ENDIF.
              ENDIF.
            ENDIF.
          ENDIF.

          IF <gs_bestandliste>-delb0 = 'K-AUFT'.
            <gs_output>-sum_bdm_kauf = <gs_output>-sum_bdm_kauf + <gs_bestandliste>-mng01.
          ENDIF.

          IF <gs_bestandliste>-delb0 = 'LIEFER'.
            <gs_output>-sum_bdm_liefer = <gs_output>-sum_bdm_liefer + <gs_bestandliste>-mng01.
          ENDIF.

          IF <gs_bestandliste>-delb0 = 'SK-BED'.
            <gs_output>-sum_bdm_sek = <gs_output>-sum_bdm_sek + <gs_bestandliste>-mng01.
          ENDIF.

          CLEAR <gs_bestandliste>-mng01.
          CLEAR <gs_bestandliste>-mng02.
        ENDLOOP.

      ENDIF.
      CLEAR gt_bestandliste_temp. REFRESH gt_bestandliste_temp.
      CLEAR gt_mdez_sum.  REFRESH gt_mdez_sum.
      CLEAR gt_mdez.  REFRESH gt_mdez.
    ENDIF.
*Wenn ckeckbox gesetzt ist, werden dann das letzte WE-Buchung
    IF chkbox = 'X'.
      CONCATENATE 'Lesen Tabelle mseg bei ' <gs_output>-matnr INTO gv_text SEPARATED BY space.

*      CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
*       EXPORTING
**             PERCENTAGE       = 0
*         TEXT             = gv_text
*                .

*Abfrage, ob Wareneingangsbuchung von einem Material vorhanden ist.
      SELECT MBLNR MJAHR MATNR BWART
            INTO CORRESPONDING FIELDS OF TABLE gt_mseg
            FROM mseg
            WHERE matnr = <gs_output>-matnr
              AND werks = '1000'
              AND ( bwart = '101' OR bwart = '601').
     IF sy-subrc = 0.
        READ TABLE gt_mseg WITH KEY bwart = '101' INTO gs_mseg.
        IF sy-subrc = 0.
          <gs_output>-weflag = 'X'.
          SORT gt_mseg BY bwart ASCENDING mjahr DESCENDING mblnr DESCENDING.
*Ermitteln das Datum der letzten Wareneingangsbuchung
          READ TABLE gt_mseg INDEX 1 INTO gs_mseg.
          IF sy-subrc = 0.
            SELECT SINGLE *
                INTO gs_mkpf
                FROM mkpf
                WHERE mblnr = gs_mseg-mblnr
                  AND mjahr = gs_mseg-mjahr.
            IF sy-subrc = 0.
              <gs_output>-welastdate = gs_mkpf-budat.
            ENDIF.
          ENDIF.
        ENDIF.

        READ TABLE gt_mseg WITH KEY bwart = '601' INTO gs_mseg.
        IF sy-subrc = 0.
          <gs_output>-weflag = 'X'.
          SORT gt_mseg BY bwart DESCENDING mjahr DESCENDING mblnr DESCENDING.
*Ermitteln das Datum der letzten Warenausgangsbuchung
          READ TABLE gt_mseg INDEX 1 INTO gs_mseg.
          IF sy-subrc = 0.
            SELECT SINGLE *
                INTO gs_mkpf
                FROM mkpf
                WHERE mblnr = gs_mseg-mblnr
                  AND mjahr = gs_mseg-mjahr.
            IF sy-subrc = 0.
              <gs_output>-walastdate = gs_mkpf-budat.
            ENDIF.
          ENDIF.
        ENDIF.
      ENDIF.

      CLEAR gs_mseg.
      CLEAR gt_mseg.
      REFRESH gt_mseg.
      CLEAR gs_mkpf.
      CLEAR gt_mkpf.
      REFRESH gt_mkpf.

    ENDIF.

*Lesen Einkaufsinfosatz
    CALL FUNCTION 'BAPI_INFORECORD_GETLIST'
       EXPORTING
*   VENDOR                    =
          MATERIAL                  = <gs_output>-matnr
*   MAT_GRP                   =
*   VEND_MAT                  =
*   VEND_PART                 =
*   VEND_MATG                 =
          PURCH_ORG                 = '1000'
*   INFO_TYPE                 =
          PLANT                     =  '1000'
*   PUR_GROUP                 =
*   PURCHASINGINFOREC         =
*   DELETED_INFORECORDS       = ' '
*   PURCHORG_DATA             = 'X'
*   GENERAL_DATA              = 'X'
*   MATERIAL_EVG              =
*   PURCHORG_VEND             = ' '
        TABLES
*   INFORECORD_GENERAL        =
          INFORECORD_PURCHORG       = gt_infosatz
          RETURN                    = gt_return
              .

    READ TABLE gt_return WITH KEY type = 'E' INTO gs_return.
*Einkaufsinfosatz-Flag setzen
    IF sy-subrc <> 0.
      IF NOT gt_infosatz[] IS INITIAL.
        <gs_output>-ekinfoflag = 'X'.
      ENDIF.
    ENDIF.

*Abfragen, ob Orderbuch vorhanden ist
    SELECT SINGLE *
        INTO gs_eord
        FROM eord
        WHERE matnr = <gs_output>-matnr
          AND werks = '1000'.

    IF sy-subrc = 0.
      <gs_output>-eordflag = 'X'.
    ENDIF.

    MODIFY gt_output INDEX output_idx FROM <gs_output> TRANSPORTING wgbez dsnam mtpos wbmng02 sum_kb nkbflag ovflag weflag waflag welastdate walastdate ekinfoflag eordflag sum_bdm_kauf sum_bdm_liefer sum_bdm_sek.
    CLEAR gs_output.
   [b][color=#FF4000] COMMIT WORK [/color][/b] 
ENDLOOP.

Vielen Dank für Eure Hilfe

cuncon

Re: Performance-Problem

Beitrag von ralf.wenzel (Top Expert / 3946 / 201 / 281 ) »
commit work verhindert keine Laufzeitprobleme, sondern setzt sozusagen (!) den Timer auf Null zurück. Du verhinderst also nur den Abbruch, das Laufzeitproblem hast du immer noch. Ein Online-Report, der 40 Minuten läuft, läuft zu lang. Der gehört entweder in den Hintergrund oder massiv beschleunigt.


Ralf

Folgende Benutzer bedankten sich beim Autor ralf.wenzel für den Beitrag:
cuncon

Bild
Ralf Wenzel Heuristika SAP-Development
25 Jahre SAP-Entwickler • 20 Jahre Freiberufler
PublikationenUngarische NotationXing

Re: Performance-Problem

Beitrag von cuncon (Specialist / 143 / 98 / 1 ) »
ralf.wenzel hat geschrieben:commit work verhindert keine Laufzeitprobleme, sondern setzt sozusagen (!) den Timer auf Null zurück. Du verhinderst also nur den Abbruch, das Laufzeitproblem hast du immer noch. Ein Online-Report, der 40 Minuten läuft, läuft zu lang. Der gehört entweder in den Hintergrund oder massiv beschleunigt.


Ralf
Aber wieso nach dem ich commit work eingebaut habe, ist das time out nicht mehr aufgetreten? Das verstehe ich auch nicht ganz. Das Programm läuft auf dem Testsystem gut im Hintergrund, aber das soll auch online gut laufen können :), leider. Ich habe gerade das Programm mit commit work auf dem Produktivsystem gestartet, mal kucken ob es klappt.
Aber wie kann man das Programm massiv beschleunigen, ich habe es versucht seit 2 Tagen schon, aber es hat nicht geklappt. Oder soll ich 2 Programme schreiben. Das 1.Programm lesen die Daten von den SAP-Tabellen und speichern die Daten in Z-Tabelle und dann dann das 1.Programm ruft das 2.Programm auf, das diese Daten aus Z-Tabelle liest und die Daten verarbeiten? Wie meint ihr? Habt ihr bessere Idee?

cuncon
Zuletzt geändert von cuncon am 01.03.2018 13:11, insgesamt 3-mal geändert.

Re: Performance-Problem

Beitrag von ralf.wenzel (Top Expert / 3946 / 201 / 281 ) »
cuncon hat geschrieben:Das Programm läuft gut im Hintergrund, aber das soll auch online gut laufen können :), leider.
Dafür ist es zu langsam - weil ein COMMIT WORK das Problem nicht löst.


Ralf

Folgende Benutzer bedankten sich beim Autor ralf.wenzel für den Beitrag:
cuncon

Bild
Ralf Wenzel Heuristika SAP-Development
25 Jahre SAP-Entwickler • 20 Jahre Freiberufler
PublikationenUngarische NotationXing

Re: Performance-Problem

Beitrag von DeathAndPain (Top Expert / 1964 / 261 / 415 ) »
Also Deinen Code finde ich beim Überfliegen erst mal nicht so verkehrt. Mein Tipp ist, dass die von Dir gerufenen SAP-Standard-Funktionsbausteine MD_STOCK_REQUIREMENTS_LIST_API und/oder BAPI_INFORECORD_GETLIST so langsam sind, dass Du bei einer hinreichend großen Anzahl Einträge einfach auf eine hohe Laufzeit kommst. Sollte ich damit richtig liegen, dann bleibt Dir nur, entweder mit der Laufzeit zu leben oder auf den Baustein zu verzichten und stattdessen selber die Daten aus der Datenbank zu lesen. Letzteres kriegt man selber eigentlich immer deutlich performanter hin als die Standard-Bausteine, wenn man weiß, in welchen Tabellen man schauen muss und wie die genauen Zusammenhänge sind, aber dafür ist man dann halt auch selbst dafür verantwortlich, dass das, was man da macht, auch inhaltlich richtig ist (auch in etwaigen Sonderfällen).

Was Du ansonsten noch tun könntest, um die Performance ein Stück nach oben zu treiben, ist, die ganzen SELECT SINGLES durch je einen großen SELECT... FOR ALL ENTRIES IN zu ersetzen und eine sortierte interne Puffertabelle damit zu füllen, aus der Du nachher in Deinen LOOPs die Daten liest. Das kostet zwar etwas Hauptspeicher, aber in einer Größenordnung, die für heutige SAP-Systeme ein Lacher ist. Du reduzierst damit die Zahl Deiner Datenbankzugriffe auf einen Bruchteil, und Datenbankzugriffe machen bei ABAP-Programmen normalerweise den allergrößten Teil der Laufzeit aus.

Womit ich an Deiner Stelle anfangen würde, ist, den wahren Laufzeitfresser zu identifizieren. Dies tust Du, indem Du in die Transaktion ST05 startest, dort auf "Trace einschalten" klickst, dann in einem anderen Modus (Fenster) Dein Programm durchlaufen lässt, dann wieder in Dein erstes Fenster wechselst, dort "Trace ausschalten" klickst und dann dort auf "Trace anzeigen" klickst. Dann bekommst Du eine Liste aller erfolgten Datenbankzugriffe. Schau Dir die verfügbaren Drucktasten und Menüeinträge an, um zu sehen, auf welche Weise Du diese Zugriffe aggregieren kannst. Finde heraus, der Zugriff auf welche Tabellen am meisten Rechenzeit verschlingt und wo diese Zugriffe angesiedelt sind. Dann siehst Du sehr schön, bei welchen Zugriffen eine Optimierung richtig was bringt.

Mit COMMIT WORK setzt Du den Timeout-Timer zurück, wie Ralf schon richtig gesagt hat. Durch immer mal wieder eingestreute COMMIT WORKs kann Dein Programm sich also in unbegrenztem Umfang Laufzeit erschleichen. Admins mögen das nur deshalb nicht, weil Timeouts einen Sinn haben und sie nicht wollen, dass marodierende Programme unbegrenzt Rechenlast erzeugen, ohne irgendwann abzubrechen. Lang laufende Berechnungsroutinen, die 40 Minuten lang volle Last erzeugen, packt man in einen Hintergrundjob, der typischerweise nachts läuft, wenn er die Anwender nicht stört. Hintergrundjobs unterliegen keinen Timeout-Beschränkungen.

Sofern es sich bei Deinem Programm um einen Report handelt, kannst Du ihn auch direkt im Hintergrund ausführen lassen, indem Du ihn nach dem Füllen des Selektionsbildes nicht mit F8 (oder Klick auf die Uhr mit grünem Haken), sondern mit F9 startest. Dann läuft er wie ein geplanter Job im Hintergrund und unterliegt keinem Timeout. Freilich siehst Du dann auch kein Ergebnisbild, weswegen Du eine Ausgabe nur der per Write-Befehl erzeugten Spooldatei (oder einer durch den Report geschriebenen Datei) entnehmen kannst.

Früher liefen im Hintergrund gestartete Programme auch etwas schneller. Ob das heute noch so ist, kann ich nicht sagen. Einen großen Unterschied gibt es da jedenfalls nicht mehr.

Folgende Benutzer bedankten sich beim Autor DeathAndPain für den Beitrag:
cuncon


Re: Performance-Problem

Beitrag von cuncon (Specialist / 143 / 98 / 1 ) »
DeathAndPain hat geschrieben:Also Deinen Code finde ich beim Überfliegen erst mal nicht so verkehrt. Mein Tipp ist, dass die von Dir gerufenen SAP-Standard-Funktionsbausteine MD_STOCK_REQUIREMENTS_LIST_API und/oder BAPI_INFORECORD_GETLIST so langsam sind, dass Du bei einer hinreichend großen Anzahl Einträge einfach auf eine hohe Laufzeit kommst. Sollte ich damit richtig liegen, dann bleibt Dir nur, entweder mit der Laufzeit zu leben oder auf den Baustein zu verzichten und stattdessen selber die Daten aus der Datenbank zu lesen. Letzteres kriegt man selber eigentlich immer deutlich performanter hin als die Standard-Bausteine, wenn man weiß, in welchen Tabellen man schauen muss und wie die genauen Zusammenhänge sind, aber dafür ist man dann halt auch selbst dafür verantwortlich, dass das, was man da macht, auch inhaltlich richtig ist (auch in etwaigen Sonderfällen).

Was Du ansonsten noch tun könntest, um die Performance ein Stück nach oben zu treiben, ist, die ganzen SELECT SINGLES durch je einen großen SELECT... FOR ALL ENTRIES IN zu ersetzen und eine sortierte interne Puffertabelle damit zu füllen, aus der Du nachher in Deinen LOOPs die Daten liest. Das kostet zwar etwas Hauptspeicher, aber in einer Größenordnung, die für heutige SAP-Systeme ein Lacher ist. Du reduzierst damit die Zahl Deiner Datenbankzugriffe auf einen Bruchteil, und Datenbankzugriffe machen bei ABAP-Programmen normalerweise den allergrößten Teil der Laufzeit aus.

Womit ich an Deiner Stelle anfangen würde, ist, den wahren Laufzeitfresser zu identifizieren. Dies tust Du, indem Du in die Transaktion ST05 startest, dort auf "Trace einschalten" klickst, dann in einem anderen Modus (Fenster) Dein Programm durchlaufen lässt, dann wieder in Dein erstes Fenster wechselst, dort "Trace ausschalten" klickst und dann dort auf "Trace anzeigen" klickst. Dann bekommst Du eine Liste aller erfolgten Datenbankzugriffe. Schau Dir die verfügbaren Drucktasten und Menüeinträge an, um zu sehen, auf welche Weise Du diese Zugriffe aggregieren kannst. Finde heraus, der Zugriff auf welche Tabellen am meisten Rechenzeit verschlingt und wo diese Zugriffe angesiedelt sind. Dann siehst Du sehr schön, bei welchen Zugriffen eine Optimierung richtig was bringt.

Mit COMMIT WORK setzt Du den Timeout-Timer zurück, wie Ralf schon richtig gesagt hat. Durch immer mal wieder eingestreute COMMIT WORKs kann Dein Programm sich also in unbegrenztem Umfang Laufzeit erschleichen. Admins mögen das nur deshalb nicht, weil Timeouts einen Sinn haben und sie nicht wollen, dass marodierende Programme unbegrenzt Rechenlast erzeugen, ohne irgendwann abzubrechen. Lang laufende Berechnungsroutinen, die 40 Minuten lang volle Last erzeugen, packt man in einen Hintergrundjob, der typischerweise nachts läuft, wenn er die Anwender nicht stört. Hintergrundjobs unterliegen keinen Timeout-Beschränkungen.

Sofern es sich bei Deinem Programm um einen Report handelt, kannst Du ihn auch direkt im Hintergrund ausführen lassen, indem Du ihn nach dem Füllen des Selektionsbildes nicht mit F8 (oder Klick auf die Uhr mit grünem Haken), sondern mit F9 startest. Dann läuft er wie ein geplanter Job im Hintergrund und unterliegt keinem Timeout. Freilich siehst Du dann auch kein Ergebnisbild, weswegen Du eine Ausgabe nur der per Write-Befehl erzeugten Spooldatei (oder einer durch den Report geschriebenen Datei) entnehmen kannst.

Früher liefen im Hintergrund gestartete Programme auch etwas schneller. Ob das heute noch so ist, kann ich nicht sagen. Einen großen Unterschied gibt es da jedenfalls nicht mehr.

Das war Anforderung von meinem Chef, dass das Programm online auch gut laufen kann. Wenn das Programm nur im Hintergrund laufen muss , dann bin ich schon lange fertig damit. Ich bin auch langsam fertig wegen diesem Problem :)

cuncon

Re: Performance-Problem

Beitrag von DeathAndPain (Top Expert / 1964 / 261 / 415 ) »
Dann wende die Ratschläge zur Performanceoptimierung an, die ich Dir in meiner vorherigen Antwort gegeben habe. Meine MM-Zeit ist zwar 10 Jahre her, so dass ich Dir keine Details mehr sagen kann, aber ich bin der Meinung, dass ich damasl Einkaufsinfosätze problemlos aus den entsprechenden Tabellen gelesen habe, ohne einen SAP-FB dafür zu brauchen. Diese FBs sind immer extrem ineffizient programmiert. Das würde ich gefühlt für den wahrscheinlichsten Performancefresser halten.

Aber fang mit dem Trace an. Danach brauchst Du nicht mehr raten; dann weißt Du, wo Deine Laufzeit herkommt.

Folgende Benutzer bedankten sich beim Autor DeathAndPain für den Beitrag:
cuncon


Re: Performance-Problem

Beitrag von cuncon (Specialist / 143 / 98 / 1 ) »
cuncon hat geschrieben:
DeathAndPain hat geschrieben:Also Deinen Code finde ich beim Überfliegen erst mal nicht so verkehrt. Mein Tipp ist, dass die von Dir gerufenen SAP-Standard-Funktionsbausteine MD_STOCK_REQUIREMENTS_LIST_API und/oder BAPI_INFORECORD_GETLIST so langsam sind, dass Du bei einer hinreichend großen Anzahl Einträge einfach auf eine hohe Laufzeit kommst. Sollte ich damit richtig liegen, dann bleibt Dir nur, entweder mit der Laufzeit zu leben oder auf den Baustein zu verzichten und stattdessen selber die Daten aus der Datenbank zu lesen. Letzteres kriegt man selber eigentlich immer deutlich performanter hin als die Standard-Bausteine, wenn man weiß, in welchen Tabellen man schauen muss und wie die genauen Zusammenhänge sind, aber dafür ist man dann halt auch selbst dafür verantwortlich, dass das, was man da macht, auch inhaltlich richtig ist (auch in etwaigen Sonderfällen).

Was Du ansonsten noch tun könntest, um die Performance ein Stück nach oben zu treiben, ist, die ganzen SELECT SINGLES durch je einen großen SELECT... FOR ALL ENTRIES IN zu ersetzen und eine sortierte interne Puffertabelle damit zu füllen, aus der Du nachher in Deinen LOOPs die Daten liest. Das kostet zwar etwas Hauptspeicher, aber in einer Größenordnung, die für heutige SAP-Systeme ein Lacher ist. Du reduzierst damit die Zahl Deiner Datenbankzugriffe auf einen Bruchteil, und Datenbankzugriffe machen bei ABAP-Programmen normalerweise den allergrößten Teil der Laufzeit aus.

Womit ich an Deiner Stelle anfangen würde, ist, den wahren Laufzeitfresser zu identifizieren. Dies tust Du, indem Du in die Transaktion ST05 startest, dort auf "Trace einschalten" klickst, dann in einem anderen Modus (Fenster) Dein Programm durchlaufen lässt, dann wieder in Dein erstes Fenster wechselst, dort "Trace ausschalten" klickst und dann dort auf "Trace anzeigen" klickst. Dann bekommst Du eine Liste aller erfolgten Datenbankzugriffe. Schau Dir die verfügbaren Drucktasten und Menüeinträge an, um zu sehen, auf welche Weise Du diese Zugriffe aggregieren kannst. Finde heraus, der Zugriff auf welche Tabellen am meisten Rechenzeit verschlingt und wo diese Zugriffe angesiedelt sind. Dann siehst Du sehr schön, bei welchen Zugriffen eine Optimierung richtig was bringt.

Mit COMMIT WORK setzt Du den Timeout-Timer zurück, wie Ralf schon richtig gesagt hat. Durch immer mal wieder eingestreute COMMIT WORKs kann Dein Programm sich also in unbegrenztem Umfang Laufzeit erschleichen. Admins mögen das nur deshalb nicht, weil Timeouts einen Sinn haben und sie nicht wollen, dass marodierende Programme unbegrenzt Rechenlast erzeugen, ohne irgendwann abzubrechen. Lang laufende Berechnungsroutinen, die 40 Minuten lang volle Last erzeugen, packt man in einen Hintergrundjob, der typischerweise nachts läuft, wenn er die Anwender nicht stört. Hintergrundjobs unterliegen keinen Timeout-Beschränkungen.

Sofern es sich bei Deinem Programm um einen Report handelt, kannst Du ihn auch direkt im Hintergrund ausführen lassen, indem Du ihn nach dem Füllen des Selektionsbildes nicht mit F8 (oder Klick auf die Uhr mit grünem Haken), sondern mit F9 startest. Dann läuft er wie ein geplanter Job im Hintergrund und unterliegt keinem Timeout. Freilich siehst Du dann auch kein Ergebnisbild, weswegen Du eine Ausgabe nur der per Write-Befehl erzeugten Spooldatei (oder einer durch den Report geschriebenen Datei) entnehmen kannst.

Früher liefen im Hintergrund gestartete Programme auch etwas schneller. Ob das heute noch so ist, kann ich nicht sagen. Einen großen Unterschied gibt es da jedenfalls nicht mehr.

Das war Anforderung von meinem Chef, dass das Programm online auch gut laufen kann. Wenn das Programm nur im Hintergrund laufen muss , dann bin ich schon lange fertig damit. Ich bin auch langsam fertig wegen diesem Problem :)

cuncon
Vielen Dank für den Tipp. Ich habe gerade das Programm mit F9 gestartet und mal kucken, wie das Ergebnis aussieht. Ich habe kein Write-Befehl geschrieben, sondern ALV-List.

Re: Performance-Problem

Beitrag von cuncon (Specialist / 143 / 98 / 1 ) »
Also, ich habe das Programm auf dem Produktivsystem gestartet mit commit work Befehl. Es gab kein timeout mehr, aber es hat 90 Minuten gedauert. Wie ihr sagtest, dass mit commit work man Ärger von Admins bekommen könnte, dann nehme ich ihn von dem Code raus, schade :).

cuncon

Re: Performance-Problem

Beitrag von DeathAndPain (Top Expert / 1964 / 261 / 415 ) »
Haste mal meine Tipps zur Performanceoptimierung versucht? Da ist eine Menge drin. Ich weiß ja nicht, welche Datenmengen Du mit dem Programm verarbeiten möchtest, aber von der Sache bin ich der Meinung, das muss mit einem einstelligen Minutenpensum machbar sein.

Folgende Benutzer bedankten sich beim Autor DeathAndPain für den Beitrag:
cuncon


Re: Performance-Problem

Beitrag von cuncon (Specialist / 143 / 98 / 1 ) »
DeathAndPain hat geschrieben:Haste mal meine Tipps zur Performanceoptimierung versucht? Da ist eine Menge drin. Ich weiß ja nicht, welche Datenmengen Du mit dem Programm verarbeiten möchtest, aber von der Sache bin ich der Meinung, das muss mit einem einstelligen Minutenpensum machbar sein.
Ich habe versucht das Programm mit F9 zu starten, es hat gut geklappt und ist wie Hintergrund gelaufen. Das fand ich cool, schon etwas Neues gelernt. Und zu deinem Vorschlag SAP Tabellen statt FUBA MD_STOCK_REQUIREMENTS_LIST_API und BAPI_INFORECORD_GETLIST zu verwenden , es ist gut, aber schon mühsam, weil ich mein Programm fast komplett umprogrammieren und herausfinden muss, welche Tabelle dafür geeignet sind. Wenn es nicht anders geht, muss ich das leider machen

cuncon

Re: Performance-Problem

Beitrag von black_adept (Top Expert / 4116 / 129 / 951 ) »
Nein - du willst nicht am MD_STOCK_REQUIREMENTS vorbeilesen.
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Re: Performance-Problem

Beitrag von DeathAndPain (Top Expert / 1964 / 261 / 415 ) »
Aber am BAPI_INFORECORD_GETLIST.

Re: Performance-Problem

Beitrag von DeathAndPain (Top Expert / 1964 / 261 / 415 ) »
Und zu deinem Vorschlag SAP Tabellen statt FUBA MD_STOCK_REQUIREMENTS_LIST_API und BAPI_INFORECORD_GETLIST zu verwenden , es ist gut, aber schon mühsam, weil ich mein Programm fast komplett umprogrammieren und herausfinden muss, welche Tabelle dafür geeignet sind.
Wieso alles umprogrammieren? Du musst doch nur den FB-Aufruf durch eine Formroutine ersetzen, in der Du die entsprechenden Tabellen liest. Und wie gesagt, ich habe dunkel in Erinnerung, dass das Lesen von Einkaufsinfosätzen von der Datenbank kein Hexenwerk war.

Vergleichbare Themen

2
Antw.
1341
Views
Performance Problem
von ChrissixD » 21.11.2017 07:49 • Verfasst in ABAP® für Anfänger
14
Antw.
3111
Views
Performance Problem
von ChrissixD » 26.09.2017 09:13 • Verfasst in ABAP® für Anfänger
18
Antw.
7151
Views
Performance-Problem bei SELECT
von Charadin » 22.10.2007 08:10 • Verfasst in ABAP® Core
8
Antw.
4734
Views
Speicher & Performance Problem bei XML einlesen
von Zubasa » 15.06.2011 13:48 • Verfasst in ABAP® für Anfänger
5
Antw.
3523
Views
Performance-Problem bei Aufruf einer SAP-Klasse
von xforce » 12.07.2018 13:19 • Verfasst in ABAP® für Anfänger

Aktuelle Forenbeiträge

Hilfe zum FB MATERIAL_MAINTAIN_DARK
Gestern von black_adept gelöst 8 / 1784
HR-Entgeltnachweis
vor 2 Tagen von ChrisB 4 / 2326

Newsletter Anmeldung

Keine Beiträge verpassen! Wöchentlich versenden wir lesenwerte Beiträge aus unserer Community.
Die letzte Ausgabe findest du hier.
Details zum Versandverfahren und zu Ihren Widerrufsmöglichkeiten findest du in unserer Datenschutzerklärung.

Aktuelle Forenbeiträge

Hilfe zum FB MATERIAL_MAINTAIN_DARK
Gestern von black_adept gelöst 8 / 1784
HR-Entgeltnachweis
vor 2 Tagen von ChrisB 4 / 2326

Unbeantwortete Forenbeiträge

Export von Spools in XLSX
vor 4 Tagen von abapamateur 1 / 361
Feldberechnung ME32K
vor einer Woche von ZF_SAPler 1 / 959
MS-Word als Editor
letzen Monat von tekko 1 / 4470