Performance im Loop verbessern


Alles rund um die Sprache ABAP®: Funktionsbausteine, Listen, ALV

Moderatoren: Jan, Steff

Performance im Loop verbessern

Beitragvon SaskuAc » 20.11.2018, 09:10

Hallo miteinander.

Ich möchte in einem BW-Extraktor die performance verbessern. Hierbei geht es ( nur als info ) um die Zeitsalden ALLER Mitarbeiter. ( heißt, das sind, wenn man die Daten auf täglicher Basis ein Mal im Monat runterlädt ca 35 Millionen Datensätze - wir sind ca 70.000 Mitarbeiter bei denen in der Tabelle dann ca 500 Einträge pro Monat stehen - und das ist noch optimistisch gerechnet, normalerweise sind es mehr einträge )

Heißt unterm Strich, dass es extrem viel Laufzeit benötigt die Daten immer zu lesen und zu verarbeiten, falls man mal einen kompletten Initial-Lauf im BW machen möchte.
Um die performance zu verbessern habe ich ein paar Punkte, welche verändert werden müssen.

Unteranderem ein Loop bei denen die Einträge der jeweiligen Zeitsalden drinnen stehen ( heißt die Tabelle mit den immer 500 Einträgen ).

Ich habe folgenden Loop:

Code: Alles auswählen
            LOOP AT lt_zes INTO DATA(ls_zes) WHERE reday = gs_bw_minutes-date+6(2) AND ( ztart EQ '0050' OR ztart EQ '0540' ).
              CASE ls_zes-ztart.
                WHEN '0050'. " productive hours
                  gs_bw_minutes-proda = ls_zes-anzhl.
                  gs_bw_minutes-propa = ls_zes-anzhl.
                WHEN '0540'. " Net productive hours
                  gs_bw_minutes-bezpa = ls_zes-anzhl.
                  gs_bw_minutes-propa = gs_bw_minutes-proda - ls_zes-anzhl.
              ENDCASE.
            ENDLOOP.


Jetzt stellt sich mir die Frage, wie kann ich das Performance Mäßig noch verbessern. Soll ich die nicht benötigten Einträge ( in dem Fall überall wo die Felder ztart nicht den benötigten entsprechen ) löschen ? Also wenn ich lösche bevor ich drüber loope. Ist das performanter als die Where Bedingung? Oder generell, wie kann ich das performance Mäßig noch verbessern?

Danke euch.
SaskuAc
Specialist
 
Beiträge: 213
Registriert: 01.06.2015, 10:16
Dank erhalten: 21 mal
Ich bin: Entwickler/in

Sponsor

Alte ABAP-Entwicklerweisheit: Weißt du weder aus noch ein, baust du einen BADI ein

Re: Performance im Loop verbessern

Beitragvon Tommy Nightmare » 20.11.2018, 09:21

Hallo SaskuAc,

generell würde ich Feldsymbole im Loop empfehlen, dann muss nicht jedes mal die Struktur ls_zes neu befüllt werden.
Konkret:
Code: Alles auswählen
*Alt:
LOOP AT lt_zes INTO DATA(ls_zes)
*Neu:
LOOP AT lt_zes ASSIGNING FIELD-SYMBOL(<ls_zes>)
 


Mit der Transaktion SAT kannst du mal analysieren, ob das was bringt.

LG Tommy
Tommy Nightmare
ForumUser
 
Beiträge: 27
Registriert: 08.09.2017, 11:38
Dank erhalten: 1 mal
Ich bin: Entwickler/in

Re: Performance im Loop verbessern

Beitragvon ewx » 20.11.2018, 09:23

Du solltest zusehen, dass du nur die Datensätze liest, du du auch benötigst.
Also in dem Fall nur die mit ZTART = { 0050 | 0540 }

Je weniger Datensätze desto besser.

Du solltest die Datensätze auch in Blöcken lesen (50.000, 100.000, 500.000, ...).
Je größer die Tabelle, desto länger dauern die Operationen.
Letztendlich ist es aber egal, ob du einen LOOP über 35 mio Datensätze machst oder 350 LOOPS über 100.000 Datensätze. Verarbeitet werden müssen sie halt...

Am besten schaust du dir in der Transaktion SAT oder im SQL-Trace ST05 an, wo die meiste Laufzeit liegt. Hier musst du mit der Optimierung anfangen.

Eine andere Möglichkeit wäre Parallelverarbeitung.
ewx
Top Expert
 
Beiträge: 3835
Registriert: 04.08.2003, 19:55
Wohnort: Schleswig-Holstein
Dank erhalten: 320 mal

Re: Performance im Loop verbessern

Beitragvon SaskuAc » 20.11.2018, 09:40

ewx hat geschrieben:Du solltest zusehen, dass du nur die Datensätze liest, du du auch benötigst.
Also in dem Fall nur die mit ZTART = { 0050 | 0540 }

Je weniger Datensätze desto besser.

Du solltest die Datensätze auch in Blöcken lesen (50.000, 100.000, 500.000, ...).
Je größer die Tabelle, desto länger dauern die Operationen.
Letztendlich ist es aber egal, ob du einen LOOP über 35 mio Datensätze machst oder 350 LOOPS über 100.000 Datensätze. Verarbeitet werden müssen sie halt...

Am besten schaust du dir in der Transaktion SAT oder im SQL-Trace ST05 an, wo die meiste Laufzeit liegt. Hier musst du mit der Optimierung anfangen.


Wenn das möglich wäre, würde ich es machen. Allerdings kann ich es hier nicht steuern.

Ich bekomme die Daten per FuBa der sich hier nicht eingrenzen lässt. Eine Maßnahme war jetzt von mir, dass ich anstatt des FuBas direkt vom HR-Cluster lese ( nimmt schon mal mehr als die hälfte der Laufzeit weg ) - da habe ich trotzdem immernoch die 35 Mio Datensätze. Davor konnte man einiges mehr rechnen. ( bin dadurch schon von 3 Stunden pro Monat auf ca. 1 Stunde runter ... )

Also selektionstechnisch ist der Extraktor einwandfrei. Es geht mir hier nur noch um die Verarbeitung, wobei das meiste in diesem Loop gemacht wird.

Mein Problem ist nicht einmal der normale Daily Business lauf, sondern der Initiallauf. Weil man dort dann ca 10 Jahre immer Monat für Monat laufen lassen muss. ( heißt 12*10 = 120 Monate * 3 Stunden = 360 Stunden Initiallauf ... Juhu... ) Und im BW kann es häufiger vorkommen, dass ein Initiallauf gemacht wird.. Leider.

ewx hat geschrieben:Eine andere Möglichkeit wäre Parallelverarbeitung.


Das schau ich mir mal an inwieweit ich hiermit arbeiten kann...

Tommy Nightmare hat geschrieben:Hallo SaskuAc,

generell würde ich Feldsymbole im Loop empfehlen, dann muss nicht jedes mal die Struktur ls_zes neu befüllt werden.
Konkret:
Code: Alles auswählen
*Alt:
LOOP AT lt_zes INTO DATA(ls_zes)
*Neu:
LOOP AT lt_zes ASSIGNING FIELD-SYMBOL(<ls_zes>)
 



Danke! Das wird bestimmt auch nochmal ein bisschen was bringen. Danke.

Meint Ihr, dass es etwas bringen könnte, wenn ich aus der internen Tabelle die Datensätze zuerst lösche, die ich nicht brauche, bevor ich per Loop drüber gehe? - Da enno meinte, "Je weniger Datensätze desto besser" schätze ich einfach mal schon, oder? ^^
SaskuAc
Specialist
 
Beiträge: 213
Registriert: 01.06.2015, 10:16
Dank erhalten: 21 mal
Ich bin: Entwickler/in

Re: Performance im Loop verbessern

Beitragvon ewx » 20.11.2018, 09:49

SaskuAc hat geschrieben:Wenn das möglich wäre, würde ich es machen. Allerdings kann ich es hier nicht steuern.
Ich bekomme die Daten per FuBa der sich hier nicht eingrenzen lässt.

Kannst du den Baustein nicht anpassen?
Eine direkte Selektion wäre dann natürlich auch eine Alternative, sofern im Baustein nicht jede Menge "Berechnungen" und "Prüfungen" gemacht werden, die du auch nachprogrammieren müsstest.

Ich verstehe auch nicht, dass du den Baustein nicht eingrenzen kannst. Wie machst du denn einen "Monatslauf"? Liest du da auch alle 35 mio. Datensätze und schränkst im Loop ein?
Ist das ein Standard-SAP-Baustein?

SaskuAc hat geschrieben:Meint Ihr, dass es etwas bringen könnte, wenn ich aus der internen Tabelle die Datensätze zuerst lösche, die ich nicht brauche, bevor ich per Loop drüber gehe?

Auch das Löschen der Datensätze kostet Zeit. Musst du am besten ausprobieren. Optimal wäre es, wie gesagt, die Sätze gar nicht erst zu lesen.

Ist der Extraktor wirklich so simpel, dass ALLE Datensätze gelesen werden und du über ALLE Datensätze einmal loopst?
Liest du irgendwelche Daten nach?
ewx
Top Expert
 
Beiträge: 3835
Registriert: 04.08.2003, 19:55
Wohnort: Schleswig-Holstein
Dank erhalten: 320 mal

Re: Performance im Loop verbessern

Beitragvon Dele » 20.11.2018, 10:08

Wenn möglich, dann die Tabelle als sortierte Tabelle (non unique) definieren:
der tag aus "reday" sollte ein Schlüsselfeld (z.B. day) sein und ztart sollte ein Schlüsselfeld sein.
Dann mit zwei Loops mit feldsymbol:
1. Loop: day = gs_bw_minutes-date+6(2) and ztart EQ '0050'
2. Loop: day = gs_bw_minutes-date+6(2) and ztart EQ '0540'
Dele
Specialist
 
Beiträge: 307
Registriert: 06.05.2005, 11:07
Dank erhalten: 47 mal

Re: Performance im Loop verbessern

Beitragvon SaskuAc » 20.11.2018, 10:28

ewx hat geschrieben:
SaskuAc hat geschrieben:Wenn das möglich wäre, würde ich es machen. Allerdings kann ich es hier nicht steuern.
Ich bekomme die Daten per FuBa der sich hier nicht eingrenzen lässt.

Kannst du den Baustein nicht anpassen?
Eine direkte Selektion wäre dann natürlich auch eine Alternative, sofern im Baustein nicht jede Menge "Berechnungen" und "Prüfungen" gemacht werden, die du auch nachprogrammieren müsstest.



Nein ich kann den nicht anpassen, da dieser einer der zentralsten SAP HR-Zeitwirtschafts Bausteine ist, den es gibt. den Kann ich nunmal auch nicht anpassen. Aber wie schon gesagt, die selektion kann ich nicht weiter eingrenzen. Aber mach dir um den FuBa keine Gedanken, den habe ich mit der Zeile
Code: Alles auswählen
IMPORT zes TO lt_zes FROM DATABASE pcl2(b2) ID ls_b2_key.
ersetzt. Bloß kann ich hier nichts mehr eingrenzen. Kann hier leider wirklich nicht mehr eine Art Where Bedingung auf ZTART machen


ewx hat geschrieben:Ich verstehe auch nicht, dass du den Baustein nicht eingrenzen kannst. Wie machst du denn einen "Monatslauf"? Liest du da auch alle 35 mio. Datensätze und schränkst im Loop ein?
Ist das ein Standard-SAP-Baustein?

SaskuAc hat geschrieben:Meint Ihr, dass es etwas bringen könnte, wenn ich aus der internen Tabelle die Datensätze zuerst lösche, die ich nicht brauche, bevor ich per Loop drüber gehe?

Auch das Löschen der Datensätze kostet Zeit. Musst du am besten ausprobieren. Optimal wäre es, wie gesagt, die Sätze gar nicht erst zu lesen.

Ist der Extraktor wirklich so simpel, dass ALLE Datensätze gelesen werden und du über ALLE Datensätze einmal loopst?
Liest du irgendwelche Daten nach?


Kurz und knapp, Ja. Im prinzip ist er so simpel. BW ruft halt immer pakete mit 100 Personen ab, Parallel. Aber dennoch kommt dadurch die riesen laufzeit zusammen.

Um es zu erklären, ich lese die Personen, selektiere ein paar stammdaten, welche aber nicht laufzeit relevant sind. Zumindest machen sie nicht so viel aus. Dann selektiere ich die Zeitdaten ( mit dem oben beschriebenen Befehl ), welche die riesige Menge an Datensätze ausmacht. Und dann mache ich den loop über die Tabelle. Dort stehen dann ungefähr 500 ( eher mehr ) Datensätze drinnen. ( 2x ZTART pro Tag, heißt ich brauche ungefähr 60 Datensätze von den 500 ).

Und diesen Loop muss ich einschränken. Das habe ich mit einem Where gemacht, aber ich habe mal gelesen, dass die where Bedingung intern zu folgendem umgewandelt wird:

Code: Alles auswählen
" alt
loop at itab into data(structure) where field1 = X and field2 = Y.
Endloop.

" umgewandelt
loop at itab into data(structure).
check structure-field1 = X and structure-field2 = Y.
endloop.  


wenn dem tatsächlich so sein sollte, verbraucht die where bedingung viel laufzeit, wenn nicht, dann kann man wohl nicht viel machen.

Dele hat geschrieben:Wenn möglich, dann die Tabelle als sortierte Tabelle (non unique) definieren:
der tag aus "reday" sollte ein Schlüsselfeld (z.B. day) sein und ztart sollte ein Schlüsselfeld sein.
Dann mit zwei Loops mit feldsymbol:
1. Loop: day = gs_bw_minutes-date+6(2) and ztart EQ '0050'
2. Loop: day = gs_bw_minutes-date+6(2) and ztart EQ '0540'


Macht das Sinn, einen 2. Loop zu bauen? Denkst du dass es wirklich schneller gemacht wird?
SaskuAc
Specialist
 
Beiträge: 213
Registriert: 01.06.2015, 10:16
Dank erhalten: 21 mal
Ich bin: Entwickler/in

Re: Performance im Loop verbessern

Beitragvon ewx » 20.11.2018, 10:50

SaskuAc hat geschrieben:
Dele hat geschrieben:Wenn möglich, dann die Tabelle als sortierte Tabelle (non unique) definieren:
der tag aus "reday" sollte ein Schlüsselfeld (z.B. day) sein und ztart sollte ein Schlüsselfeld sein.
Dann mit zwei Loops mit feldsymbol:
1. Loop: day = gs_bw_minutes-date+6(2) and ztart EQ '0050'
2. Loop: day = gs_bw_minutes-date+6(2) and ztart EQ '0540'


Macht das Sinn, einen 2. Loop zu bauen? Denkst du dass es wirklich schneller gemacht wird?


Wenn du im Extremfall immer einen 0050-Satz und einen 0540-Satz abwechselnd hast, dann kann es deutlich schneller werden.
Eine sortierte Tabelle ist in jedem Fall sinnvoll, denke ich:
http://zevolving.com/2009/12/parallel-c ... sted-loop/

Das habe ich gerade gelernt: Stichwort "Branch prediction"
Bin mir nicht sicher, ob das auch (oder gerade) bei Schleifen gilt.

Bei 35 mio. Datensätzen sicherlich relevant: Der Datentransport ist nach wie vor die größte Schwachstelle. Ein moderner Prozessor kann deutlich mehr Daten verarbeiten, als nachgelesen werden kann. Deswegen versucht der Prozessor möglichst viel sinnvolle Daten in seinen Level-1 Cache zu holen. Dafür muss er Annahmen treffen, welche Daten sinnvoll sind. Wenn diese Annahmen aber durch völlig "unszusammenhängende Daten" nicht möglich sind, hat der Prozessor doppelte Arbeit: Er muss die ganzen gelesen Daten wieder verwerfen und neu lesen. Und das dauert. Ich hatte vor Kurzem einen anschaulichen Artikel/ Video dazu gesehen. Finde ich allerdings nicht mehr... :(
ewx
Top Expert
 
Beiträge: 3835
Registriert: 04.08.2003, 19:55
Wohnort: Schleswig-Holstein
Dank erhalten: 320 mal

Re: Performance im Loop verbessern

Beitragvon Dele » 20.11.2018, 11:25

Macht das Sinn, einen 2. Loop zu bauen? Denkst du dass es wirklich schneller gemacht wird?


Es hängt davon ab, wie der ABAP-Prozessor mit dem OR umgeht. Wenn er nur den ersten Schlüssel (also day) nimmt, dann werden alle Einträge zum Tag gelesen und die OR-Bedingung dient nur als Filter. Kann aber auch sein, dass der ABAP-Prozessor intelligenter ist.

Aber ich weiß, dass einige Datenbanken bei OR Bedingungen und bei Negativ-Vergleichen Schwierigkeiten haben.

Probieren geht über studieren. :D
Dele
Specialist
 
Beiträge: 307
Registriert: 06.05.2005, 11:07
Dank erhalten: 47 mal

Re: Performance im Loop verbessern

Beitragvon nickname8 » 20.11.2018, 12:44

Paar Ideen:
- Wie breit ist die Struktur von lt_zes? Wenn sie sehr breit ist, guck dir dieses Video mal an: https://www.youtube.com/watch?v=2nfA_tK8HbA
- Entweder du nutzt eine SORTED TABLE (wie Dele vorgeschalgen hat), oder du sortierst die vorhandene Tabelle nach "REDAY" und nach "ZTART" und nutzt parallel cursor (suche nach ZTART = 0050 BINARY SEARCH und dann im LOOP den Befehl FROM sy-tabix und am Anfang des Loops prüfen, ob es noch 0050 ist. Das gleiche dann mit 0540).
- Alle WHERE-Bedingungen müssen mit AND verknüpft sein. In dem Buch "Besseres ABAP" werden hier auf die SAP Hinweise 1495892, 1409179 und 1523839 verwiesen. Habe grade kein Zugang um mir die durchzulesen.

Der Rest wurde schon erwähnt. Bei der Menge ist auf jeden Fall die "Parallele Verarbeitung" (von Enno vorgeschlagen) interessant. Habe ich spaßeshalber schonmal implementiert und hat auch echt Zeit gespart.
nickname8
ForumUser
 
Beiträge: 78
Registriert: 18.07.2015, 08:22
Dank erhalten: 10 mal
Ich bin: Entwickler/in

Re: Performance im Loop verbessern

Beitragvon nickname8 » 20.11.2018, 12:49

ewx hat geschrieben:Das habe ich gerade gelernt: Stichwort "Branch prediction"
Bin mir nicht sicher, ob das auch (oder gerade) bei Schleifen gilt.

Bei 35 mio. Datensätzen sicherlich relevant: Der Datentransport ist nach wie vor die größte Schwachstelle. Ein moderner Prozessor kann deutlich mehr Daten verarbeiten, als nachgelesen werden kann. Deswegen versucht der Prozessor möglichst viel sinnvolle Daten in seinen Level-1 Cache zu holen. Dafür muss er Annahmen treffen, welche Daten sinnvoll sind. Wenn diese Annahmen aber durch völlig "unszusammenhängende Daten" nicht möglich sind, hat der Prozessor doppelte Arbeit: Er muss die ganzen gelesen Daten wieder verwerfen und neu lesen. Und das dauert. Ich hatte vor Kurzem einen anschaulichen Artikel/ Video dazu gesehen. Finde ich allerdings nicht mehr... :(


Wenn du das mal wieder finden solltest, stell es gerne rein. Fände ich sehr interessant.
nickname8
ForumUser
 
Beiträge: 78
Registriert: 18.07.2015, 08:22
Dank erhalten: 10 mal
Ich bin: Entwickler/in

Re: Performance im Loop verbessern

Beitragvon black_adept » 20.11.2018, 13:58

ewx hat geschrieben: Das habe ich gerade gelernt: Stichwort "Branch prediction"
Bin mir nicht sicher, ob das auch (oder gerade) bei Schleifen gilt.
[...] Ich hatte vor Kurzem einen anschaulichen Artikel/ Video dazu gesehen. Finde ich allerdings nicht mehr... :(

War das nicht einer der Vorträge auf eurem SAP Inside-Track? Dann weißt du auch wo du suchen solltest.
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de
black_adept
Top Expert
 
Beiträge: 3131
Registriert: 08.01.2003, 13:33
Wohnort: Lehrte ( bei Hannover )
Dank erhalten: 533 mal
Ich bin: Freiberufler/in

Re: Performance im Loop verbessern

Beitragvon ewx » 20.11.2018, 14:09

black_adept hat geschrieben:
ewx hat geschrieben: Das habe ich gerade gelernt: Stichwort "Branch prediction"
Bin mir nicht sicher, ob das auch (oder gerade) bei Schleifen gilt.
[...] Ich hatte vor Kurzem einen anschaulichen Artikel/ Video dazu gesehen. Finde ich allerdings nicht mehr... :(

War das nicht einer der Vorträge auf eurem SAP Inside-Track? Dann weißt du auch wo du suchen solltest.

Ja, Dmitrii hatte einen ähnlichen Vortrag gehalten, aber ich meinte noch was anderes... ;)

Beiträge über branch prediction gibt es ja einige. Aber der, den ich neulich gesehen hatte, hatte es so erklärt, dass auch ich es verstanden habe... :)
ewx
Top Expert
 
Beiträge: 3835
Registriert: 04.08.2003, 19:55
Wohnort: Schleswig-Holstein
Dank erhalten: 320 mal


Zurück zu ABAP® Core

  Aktuelle Beiträge   
Applikations-Toolbar dynamisch erzeugen
vor 8 Stunden von ralf.wenzel 0 Antw.
CP_BD_DIRECT_INPUT_PLAN
Gestern von Gottschall 0 Antw.
Logische Datenbank: Selektieren mit Loop
vor 4 Stunden von deejey 12 Antw.
Globale Konstanten - Organisationseinheiten
vor 13 Stunden von ralf.wenzel 5 Antw.
Kein Zugriff auf Dateien im Applikationsserver
Gestern von zzcpak 1 Antw.

  Ähnliche Beiträge beta
Performance bei der Klassifizierung verbessern???
11.08.2016, 16:52 von ralf.wenzel 4 Antw.
Performance testen?
13.05.2004, 10:22 von Gast 6 Antw.
Performance bei Intervallbildung
15.07.2004, 10:09 von hajo 0 Antw.
Daten-View und Performance
04.11.2006, 15:35 von gabap 2 Antw.
Performance Material -> Fertigungsauftrag?
13.02.2007, 10:15 von Kojak 0 Antw.

 

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder

cron