Wenn es eine sortierte Tabelle ist und WHERE ein Anfangsstück des Schlüssels ist: Nein
Das bedeutet nicht zwingend, dass du eine Tabelle vom Typ SORTED TABLE hast!
Folgende Benutzer bedankten sich beim Autor DeathAndPain für den Beitrag:
SaskuAc
Nachdem mein Problem offenbar nicht so ganz einfach zu lösen ist, wird das wohl nötig.DeathAndPain hat geschrieben: ↑15.11.2019 15:03Also zum einen wäre es an dieser Stelle extrem hilfreich, wenn Du den betreffenden Code selbst posten könntest, anstatt nur darüber zu schreiben. Wer weiß, was da drinsteht, was Dir nicht aufgefallen ist und was wir nicht erkennen können, wenn wir es nicht zu sehen bekommen.
Dieses select macht keine Geschwindigkeitsprobleme.Zum anderen hängt die Performance von FOR ALL ENTRIES IN sehr davon ab, ...
Ich hab jetzt einmal eine sorted table draus gemacht, hat nichts gebracht.
Code: Alles auswählen.
DATA: lw_vbpa TYPE vbpa,
lt_vbpa TYPE SORTED TABLE OF vbpa
WITH UNIQUE KEY vbeln posnr parvw,
*...
* hier kommt ein initiales select, das hier nur unnötig sperrig wäre;
* Ergebnis: lt_select_tab
*...
* dieses select geht schnell:
SELECT * FROM vbpa INTO TABLE lt_vbpa
FOR ALL ENTRIES IN lt_select_tab
WHERE vbeln = lt_select_tab-vbeln.
LOOP AT lt_select_tab INTO lw_select_tab.
*...
MOVE-CORRESPONDING lw_select_tab TO lw_grid_tab.
*...
*frühere Version, wo das loop schneller war:
* CLEAR lt_vbpa.
* SELECT * FROM vbpa INTO TABLE lt_vbpa
* WHERE vbeln = lw_grid_tab-vbeln
* AND ( posnr = 0 OR posnr = lw_grid_tab-posnr ).
* jetzt mit obigem select vbap:
LOOP AT lt_vbpa INTO lw_vbpa
WHERE vbeln = lw_grid_tab-vbeln
AND ( posnr = 0 OR posnr = lw_grid_tab-posnr ).
CASE lw_vbpa-parvw.
*...
Evtl. hilft dir dieser Link: https://blogs.sap.com/2007/09/12/runtim ... al-tables/
Danke, war an sich interessant, aber hat jetzt keine großartigen Auswirkungen - es wird empfohlen, eine sorted table zu verwenden, was ich mittlerweile tue und jetzt auch nicht wirklich was gebracht hat.JHM hat geschrieben: ↑18.11.2019 09:28Evtl. hilft dir dieser Link: https://blogs.sap.com/2007/09/12/runtim ... al-tables/
Dort wird das "Laufzeitverhalten" bei nested loops erklärt.
Das Problem ist, dass es Positionspartner geben kann oder auch nicht - das OR kann ich nur mitDas OR in der WHERE-Bedingung ist mMn nicht gerade förderlich, find aber gerade keinen Beleg. Evtl. wären zwei bedingte READ TABLE je Partnerart performanter.
Die VBPA ist nicht sehr "breit", und wie gesagt, das (derzeitige) SELECT auf vbpa ist eh schnell - würde eine "schmälere" interne Tabelle wesentlich schneller sein? Ich würde es jetzt einmal nicht erwarten.Du ließt im allgemeinen sehr viele Daten (SELECT *), verwendest du alle?
Grob die Hälfte der Partner brauche ich aktuell. Das kann ich einmal probieren... tatsächlich, das hat das Programm schneller gemacht als in der ersten Version!Benötigst du wirklich alle PARVW aus der VBPA?
Datensparsamkeit kommt der Laufzeit immer zu Gute.
field symbols muss ich mir erst anschauen - wir sind hier immerhin im Anfänger-Berech ;)Zumal du mit Arbeitsbereichen anstatt Field-Symbols bei den LOOPs arbeitest. Es müssen sehr viele Daten "kopiert" werden in deinem Loop.
Code: Alles auswählen.
LOOP AT lt_vbpa ASSIGNING FIELD-SYMBOL(<lw_vbpa>) WHERE vbeln = lw_grid_tab-vbeln
AND posnr = '000000'.
PERFORM whatever_you_wanna_do USING <lw_vbpa>.
ENDLOOP.
LOOP AT lt_vbpa ASSIGNING <lw_vbpa> WHERE vbeln = lw_grid_tab-vbeln
AND posnr = lw_grid_tab-posnr.
PERFORM whatever_you_wanna_do USING <lw_vbpa>.
ENDLOOP.
naja, auf Gleichheit prüfe ich ja, nur mit OR... aber wenn das das Problem ist...DeathAndPain hat geschrieben: ↑18.11.2019 12:36Das mit den FIELD-SYMBOLS sollte man generell machen, aber es bringt nicht viel und taugt nicht wirklich als Erklärung. Die würde ich schon eher in dem OR sehen. Dadurch, dass Du so eine komplexe Bedingung für die Positionsnummer angibst, kann das System den Index Deiner internen Tabelle auf dieselbe nicht nutzen. Indizes lassen sich nur nutzen, wenn auf Gleichheit geprüft wird (beim letzten Kriterium auch auf größer/kleiner).
Nicht den vollen, denn parvw gehört auch noch dazu, und damit kommts dann meiner READ-Struktur gleich.Nach meiner Überzeugung wärst Du schneller, wenn Du folgendes machen würdest (hier gleich in der Fassung mit Feldsymbol; ginge äquivalent aber auch ohne):
Dann nutzt jeder Zugriff auf die lt_vbpa den vollen Index VBLEN/POSNR, den Du bei der Definition Deiner internen Tabelle angegeben hast.Code: Alles auswählen.
LOOP AT lt_vbpa ASSIGNING FIELD-SYMBOL(<lw_vbpa>) WHERE vbeln = lw_grid_tab-vbeln AND posnr = '000000'. PERFORM whatever_you_wanna_do USING <lw_vbpa>. ENDLOOP. LOOP AT lt_vbpa ASSIGNING <lw_vbpa> WHERE vbeln = lw_grid_tab-vbeln AND posnr = lw_grid_tab-posnr. PERFORM whatever_you_wanna_do USING <lw_vbpa>. ENDLOOP.
Es ist noch komplexer: Vertriebsbelege haben manchmal viele, manchmal wenige Positionen, und Positionspartner gibts wiederum gar nicht so oft, aber wenn es sie gibt, muss ich sie nehmen.Ich staune zwar, dass Deine Vertriebsbelege so viele Positionen haben, dass das einen nennenswerten Unterschied macht,
Das hätte ich jetzt beinahe überlesen...Der zweite Punkt ist der, dass Du mit dem Vergleich POSNR = 0 ein NUMC mit einem INT vergleichst. Das kann ABAP zwar, aber auch dadurch geht im LOOP die Indexnutzung den Bach runter. Schreib daher korrekt den Initialwert von POSNR, also '000000'.
Logisch ja, aber syntaktisch erzeugst Du mit Deinem OR eine Komplexität, die der ABAP-Interpreter hinsichtlich der Indexnutzung nicht mehr auflösen kann. Der will einfach die einzelnen Indexelemente mit AND verknüpft in der Reihenfolge sehen, wie sie auch in Deiner Tabellendeklaration stehen.naja, auf Gleichheit prüfe ich ja, nur mit OR... aber wenn das das Problem ist...
Das habe ich gesehen, aber den schränkst Du ja nicht ein, willst also alle Sätze davon haben. Andernfalls würde ein LOOP ja auch keinen Sinn machen, denn wenn Du den vollständigen Schlüssel einer mit UNIQUE KEY deklarierten Tabelle angeben würdest, könntest Du maximal ein Ergebnis erhalten und wärst daher mit READ TABLE oder der moderneren Release 4.70-Syntax davon besser aufgestellt.Nicht den vollen, denn parvw gehört auch noch dazu
Wenn das durch die Prüfung auf POSNR IS INITIAL repräsentiert wird, dann könntest Du da auch nochmal optimieren und meinen Codevorschlag wie folgt umstellen:(ich steh pro Zeile des äußeren loops auf der Pos, und ich muss zuerst schauen, ob es einen Pos-Partner gibt, sonst auf den Kopf-Partner zurückgreifen)
Code: Alles auswählen.
LOOP AT lt_vbpa ASSIGNING FIELD-SYMBOL(<lw_vbpa>) WHERE vbeln = lw_grid_tab-vbeln
AND posnr = lw_grid_tab-posnr.
PERFORM whatever_you_wanna_do USING <lw_vbpa>.
ENDLOOP.
IF sy-subrc <> 0.
LOOP AT lt_vbpa ASSIGNING <lw_vbpa> WHERE vbeln = lw_grid_tab-vbeln
AND posnr = '000000'.
PERFORM whatever_you_wanna_do USING <lw_vbpa>.
ENDLOOP.
ENDIF.
Du weißt aber, dass es ABAP-Befehle zur Laufzeitmessung gibt? Lies Dir mal die F1-Hilfe von GET RUN TIME durch.so genau mein Daumen bei 21s stoppen kann
Code: Alles auswählen.
READ TABLE lt_vbpa
WITH KEY vbeln = lw_grid_tab-vbeln
posnr = lw_grid_tab-posnr
parvw = 'AG'
INTO lw_vbpa.
IF sy-subrc NE 0.
READ TABLE lt_vbpa
WITH KEY vbeln = lw_grid_tab-vbeln
posnr = '000000'
parvw = 'AG'
INTO lw_vbpa.
ENDIF.