Alternative For All Entries

Getting started ... Alles für einen gelungenen Start.
24 Beiträge / Seite 1 von 2 (current) Nächste
24 Beiträge Seite 1 von 2 (current) Nächste

Alternative For All Entries

Beitrag von L0w-RiDer (ForumUser / 97 / 10 / 1 ) » 11. Feb 2019 15:33

Hallo,

ich wollte mir hier mal ein paar Meinungen und Ratschläge einholen und zwar habe ich folgendes Problem. Ich selektiere aus einer Datenbanktabelle bestimmte Werte mit Einschränkungen auf einer anderen Tabelle (Treibertabelle) per For All Entries. Nun ist das alles sehr langsam, deshalb wollte ich mal fragen was es für Möglichkeiten geben würde den Code umzustellen oder andere Optionen im Vergleich zum For all Entries um das Ganze performanter zu gestalten.

Vielen Dank.

Dies wäre der Code: ( Ich hab es aus Datenschutzgründen etwas abgeändert, aber der Sinn ist der gleiche)

Code: Alles auswählen.

   SELECT t~feld1 t~feld2 t~feld3 t~feld4
        FROM Tiban AS t
        INNER JOIN lfa1 AS k
        ON t~tabkey = k~lifnr
        INTO TABLE itab1
        FOR ALL ENTRIES IN itabtr
        Where   k~erdat   => itabtr-erdat
        AND   t~iban    =  itabtr-iban. 


Re: Alternative For All Entries

Beitrag von A6272 (Specialist / 114 / 1 / 9 ) » 11. Feb 2019 16:41

Hallo,

die Indizes auf den Tabellen sind passend zur Selektion?

Grüße
Alex

Re: Alternative For All Entries

Beitrag von A6272 (Specialist / 114 / 1 / 9 ) » 11. Feb 2019 16:47

oder alles ertmal laden und dann per FILTER das unerwünsche entfernen.

Re: Alternative For All Entries

Beitrag von SaskuAc (Specialist / 246 / 18 / 27 ) » 12. Feb 2019 06:50

A6272 hat geschrieben:oder alles ertmal laden und dann per FILTER das unerwünsche entfernen.
uff... ich kenne die Tabelle Tiban nicht, aber das würde ich, im allgemeinen, nicht raten. Das wird performance mäßig nichts bringen, insbesondere wenn die Anzahl der Einträge groß ist. Ich würde, wie A6272 schon geschrieben hat, die Indizes mal überprüfen und dann noch schauen ob man bei der WHERE Bedingung nicht noch mehr eingrenzen kann..

wobei ich den Hinweis beim Tricktresor sehr hilfreich finde:
https://www.tricktresor.de/blog/verwend ... entries-2/
Wenn die Tabelle, zu der andere Einträge gelesen werden sollen, leer ist, dann werden alle Einträge der anderen Tabelle gelesen!!!
Heißt also, immer davor ein if zu setzen:

Code: Alles auswählen.

if lines( itab ) > 0. 
   select .... for all entries ... . 
endif. 
Ansonsten google einfach mal "ABAP FOR ALL ENTRIES PERFORMANCE" dann bekommst du einen haufen ergebnisse die dir hier eventuell weiterhelfen.
3 Links die allgemein Performance Tipps geben:

http://zevolving.com/2012/05/performanc ... l-entries/

https://wiki.scn.sap.com/wiki/display/C ... mance+tips

https://wiki.scn.sap.com/wiki/display/A ... and+Tuning

evtl. einfach mal mit einem der unzähligen Perfomance-Analysen Tools der SAP mal nachschauen was da so langsam läuft..

Re: Alternative For All Entries

Beitrag von deejey (Specialist / 196 / 48 / 16 ) » 12. Feb 2019 08:41

L0w-RiDer hat geschrieben:Hallo,

ich wollte mir hier mal ein paar Meinungen und Ratschläge einholen und zwar habe ich folgendes Problem. Ich selektiere aus einer Datenbanktabelle bestimmte Werte mit Einschränkungen auf einer anderen Tabelle (Treibertabelle) per For All Entries. Nun ist das alles sehr langsam, deshalb wollte ich mal fragen was es für Möglichkeiten geben würde den Code umzustellen oder andere Optionen im Vergleich zum For all Entries um das Ganze performanter zu gestalten.

Vielen Dank.

Dies wäre der Code: ( Ich hab es aus Datenschutzgründen etwas abgeändert, aber der Sinn ist der gleiche)

...
Weiß garnicht ob das hier erlaubt ist

Re: Alternative For All Entries

Beitrag von ralf.wenzel (Top Expert / 3372 / 146 / 213 ) » 12. Feb 2019 08:59

Da es nur um eine Anweisung geht und nicht um eine Kundentabelle und gerade diese Anweisung Schwierigkeiten macht, ist das problematisch und muss er dann mit allgemeinen Antworten leben. Längere Codingstrecken würde ich auch sinnerhaltend anonymisieren, einzelne Anweisungen, die keine Firmendaten enthalten, eher nicht.

Ralf

Re: Alternative For All Entries

Beitrag von DeathAndPain (Top Expert / 1012 / 115 / 223 ) » 12. Feb 2019 10:43

Im Sinne der Beantwortung von lowriders Frage denke ich, dass die Diskussion (abgesehen von der kleinen Anmerkung von A6272) hier in eine falsche Richtung geht. Der Knackpunkt ist nicht das FOR ALL ENTRIES IN. Das ist im Gegenteil eine sehr performante Konstruktion, wenn die Systemparameter für die verwendete Datenbank passend eingestellt sind.

Was mir zunächst mal auffällt, ist die seitenverdrehte Prüfung in ON-Statement. Statt ON t~tabkey = k~lifnr müsste es ON k~lifnr = t~tabkey lauten, denn im ON-Statement soll ja der Zugriff auf k (a.k.a. lfa1) eingeschränkt werden, und da schreibt man das zu prüfende Feld links und den Prüfwert rechts. Ich staune, dass das so syntaktisch überhaupt akzeptiert wird. Es kann natürlich sein, dass der ABAP-Compiler die Ungenauigkeit erkennt und im Hintergrund ausgleicht. Genauso gut aber könnte ich mir vorstellen, dass dies dazu führt, dass auf der lfa1 der Index nicht mehr genutzt wird.

Auch im WHERE-Statement würde ich mit der Primärtabelle des JOINs anfangen, obwohl ich mir an dieser Stelle ziemlich sicher bin, dass der Datenbankoptimierer sich das passend zurechtsortiert. Aber je sauberer formuliert, desto besser, und minimal verbessert das die Lesbarkeit des Codes, da ja über die TIBAN eingestiegen wird und daher im WHERE auch zunächst der indexrelevante Schlüssel der TIBAN stehen sollte. Zum Stichpunkt "Lesbarkeit" möchte ich auch dringend empfehlen, bei SELECTs wie diesem auf die Verwendung von Aliasen zu verzichten, mit denen man nur wenige Tastenanschläge spart, aber ein drastisch schlechter lesbares und verständliches Konstrukt erhält.

Ansonsten könnte man es auch ohne JOIN versuchen:

Code: Alles auswählen.

SELECT FELD1 FELD2 FELD3 FELD4
  FROM TIBAN AS T
  INTO TABLE ITAB1
  FOR ALL ENTRIES IN ITABTR
  WHERE IBAN = ITABTR-IBAN
  AND EXISTS ( SELECT * FROM LFA1
                WHERE LIFNR = TIBAN~TABKEY
                  AND ERDAT >= ITABTR-ERDAT ).
Wenn das auch nichts bringt, dann würde ich dringendst die Systemparameter prüfen, die die Verarbeitung des FOR ALL ENTRIES IN steuern. Diese müssen datenbankabhängig gesetzt werden. Es gibt diverse SAP-Hinweise dazu. Man sollte die Parameter so setzen, dass der FOR ALL ENTRIES IN datenbankseitig in einen IN-Operator übersetzt wird. Bei Oracle-Datenbanken muss für alle 5 Werte ein neuer Zugriff abgesetzt werden, bei einer SYBASE-Datenbank alle 128 Werte (so meine Erinnerung aus dem Kopf).

Re: Alternative For All Entries

Beitrag von Haubi (Expert / 602 / 12 / 26 ) » 12. Feb 2019 15:37

DeathAndPain hat geschrieben: Was mir zunächst mal auffällt, ist die seitenverdrehte Prüfung in ON-Statement. Statt ON t~tabkey = k~lifnr müsste es ON k~lifnr = t~tabkey lauten, denn im ON-Statement soll ja der Zugriff auf k (a.k.a. lfa1) eingeschränkt werden, und da schreibt man das zu prüfende Feld links und den Prüfwert rechts. Ich staune, dass das so syntaktisch überhaupt akzeptiert wird. Es kann natürlich sein, dass der ABAP-Compiler die Ungenauigkeit erkennt und im Hintergrund ausgleicht. Genauso gut aber könnte ich mir vorstellen, dass dies dazu führt, dass auf der lfa1 der Index nicht mehr genutzt wird.
Das ist in der Tat egal: der Optimizer stellt sich das so hin wie er es braucht.

Entscheidend ist festzustellen, woran es eigentlich liegt:
Zugriffspfad
Sind Felder der WHERE-Klauseln in Indizes, die benutzt werden können? Werden die Indizes auch tatsächlich vom Optimizer gewählt? Wenn nicht, warum?

Datenmenge
Wie groß ist die Treibertabelle? Da hier tatsächlich eine Aufteilung stattfindet (wie schon geschrieben 5er-Blöcke o.ä.) vervielfacht sich die Anzahl der DB-Zugriffe. Wenn also 100 Einträge in der Treibertabelle sind werden daraus (im Beispiel) 20 DB-Zugriffe.
Wie groß ist die Ergebnismenge? (Da im Beispiel nur 4 Felder aufgeführt sind ist dieser Punkt vermutlich zu vernachlässigen. Aber Datentransport ist immer ein potentielles Thema.)

Datenbankpuffer
Jeder Zugriff (naja, fast jeder), der sich des DB-Puffers bedient ist fix. Merkt man daran, dass die erste Ausführung langsam, alle weiteren schnell sind. Hierbei ist auch zu beachten, dass der Puffer in Test-Systemen häufig eher klein, in Produktivsystemen zumindest ausreichend dimensioniert ist. Es wäre also wichtig, das Verhalten des Statements in dem System zu untersuchen, in dem das Problem auftritt.

Generell hilft es, das Statement mal durch die ST05 zu jagen und das Ergebnis zu analysieren, ggf. zusammen mit einem DB-Admin. Der müsste dann auch alle relevanten Basis-Parameter kennen (rsdb/max_blocking_factor, rsdb/prefer_in_itab_opt und wie sie alle heißen).
Ach ja: welche Datenbank ist das überhaupt?

Grüße,
Haubi
Das ABAP Kochbuch ab sofort bei Amazon...

I'd rather write code that writes code than write code...
.. ..|. |.|| ||| ..| |.|. .| |. .|. . .| |.. | .... .. ... |.|| ||| ..| |.. ||| |. | |. . . |.. ||. .|.. .| ... ... . ...

Re: Alternative For All Entries

Beitrag von DeathAndPain (Top Expert / 1012 / 115 / 223 ) » 12. Feb 2019 15:48

Zugriffspfad
Sind Felder der WHERE-Klauseln in Indizes, die benutzt werden können?
Ja, das ist hier trivial gegeben. Die lfa1 hat als einziges Primärschlüsselfeld LIFNR, und die TIBAN hat einen expliziten Index auf dem Feld IBAN. Der SELECT ist einfach genug, dass kein Datenbankoptimizer ein Problem haben sollte, damit einen korrekten Indexzugriff hinzubekommen.
Datenmenge
Wie groß ist die Treibertabelle?
Wir reden von der Tabelle lfa1 der Lieferanten. Wieviele Lieferanten soll die Firma des Threaderstellers haben? Da wäre vierstellig schon viel. Das sind keine problematischen Größenordnungen.
Da hier tatsächlich eine Aufteilung stattfindet (wie schon geschrieben 5er-Blöcke o.ä.) vervielfacht sich die Anzahl der DB-Zugriffe. Wenn also 100 Einträge in der Treibertabelle sind werden daraus (im Beispiel) 20 DB-Zugriffe.
Anders herum gesprochen ist es nur noch ein Fünftel der Zugriffe verglichen mit dem klassischen Ansatz, die EInträge per SELECT SINGLE einzeln durchzugehen.

Bei Sybase sinkt die Zahl der Zugriffe gar auf weniger als 1%.

Immer vorausgesetzt, dass die Systemparameter passend eingestellt sind. Die knackigsten hast Du ja gerade genannt.

Re: Alternative For All Entries

Beitrag von deejey (Specialist / 196 / 48 / 16 ) » 12. Feb 2019 21:02

Weiß nicht ob es bereits gesagt wurde:

- itab doppelte Einträge entfernen, weiß nicht ob SAP oder die DB das implizit macht
- vermutlich ist es langsamer :D aber wenn es nicht zu viele Einträge sind (da gibt es Grenzen) als Ranges-Tabelle WHERE ... IN ... ist vlt. einen Versuch wert

Re: Alternative For All Entries

Beitrag von DeathAndPain (Top Expert / 1012 / 115 / 223 ) » 13. Feb 2019 09:01

- itab doppelte Einträge entfernen, weiß nicht ob SAP oder die DB das implizit macht
Das macht SAP bei FOR ALL ENTRIES IN automatisch.
- vermutlich ist es langsamer :D aber wenn es nicht zu viele Einträge sind (da gibt es Grenzen) als Ranges-Tabelle WHERE ... IN ... ist vlt. einen Versuch wert
Performancemäßig wird das keine Vorteile bringen. Das muss ja auch in SQL für die Datenbak übersetzt werden; da kann er ja nicht mehr machen, als doch wieder die Werte einzeln aufzuzählen.

Da würde ich eher zu der zuvor von mir genannten Subquery raten. Dann ist es wirklich nur eine einzige Anfrage, und alles andere passiert im Inneren der Datenbank (da Subquerys sich direkt in Native SQL übersetzen lassen).

Re: Alternative For All Entries

Beitrag von a-dead-trousers (Top Expert / 3199 / 81 / 792 ) » 13. Feb 2019 09:14

DeathAndPain hat geschrieben:
- itab doppelte Einträge entfernen, weiß nicht ob SAP oder die DB das implizit macht
Das macht SAP bei FOR ALL ENTRIES IN automatisch.
Jein.
ABAP Hilfe hat geschrieben: * Bezüglich doppelt vorkommender Zeilen in der Ergebnismenge wirkt der Zusatz FOR ALL ENTRIES so, als sei der Zusatz DISTINCT in der Definition der Selektionsmenge angegeben. Im Unterschied zu DISTINCT werden die Zeilen aber nicht immer vom Datenbanksystem sondern unter Umständen erst auf dem Applikationsserver aus der Ergebnismenge entfernt. Die doppelten Zeilen werden dann vom Datenbanksystem entfernt, wenn die SELECT-Anweisung als eine einzige SQL-Anweisung an das Datenbanksystem übergeben werden kann. Falls die SELECT-Anweisung auf mehrere SQL-Anweisungen verteilt übergeben werden muss, findet die Verdichtung auf dem Applikationsserver statt.
* Wenn doppelte Zeilen erst auf dem Applikationsserver entfernt werden, werden in manchen Konstellationen alle durch die WHERE-Bedingung spezifizierten Zeilen an eine interne Systemtabelle übergeben und in dieser verdichtet. Die maximale Größe dieser Systemtabelle ist wie die normaler interner Tabellen beschränkt. Insbesondere wird die Systemtabelle immer benötigt, wenn gleichzeitig einer der Zusätze PACKAGE SIZE oder UP TO n ROWS verwendet wird. Diese wirken dann nicht auf die Menge der vom Datenbankserver an den Applikationsserver übergebenen Zeilen, sondern werden erst für die Übergabe der Zeilen von der Systemtabelle an den eigentlichen Zielbereich verwendet. Wenn die maximale Größe der internen Systemtabelle überschritten wird, kommt es zu einem Laufzeitfehler.
DeathAndPain hat geschrieben:
- vermutlich ist es langsamer :D aber wenn es nicht zu viele Einträge sind (da gibt es Grenzen) als Ranges-Tabelle WHERE ... IN ... ist vlt. einen Versuch wert
Performancemäßig wird das keine Vorteile bringen. Das muss ja auch in SQL für die Datenbak übersetzt werden; da kann er ja nicht mehr machen, als doch wieder die Werte einzeln aufzuzählen.
Doch, performancemäßig bringt das einiges, weil die Werte an die Datenbank in viel größeren Paketen übergeben werden können. Z.b. unter Oracle, wo die Übergabe bei FOR ALL ENTRIES ja standardmäßig mit nur 5 eingestellt ist.
DeathAndPain hat geschrieben:Da würde ich eher zu der zuvor von mir genannten Subquery raten. Dann ist es wirklich nur eine einzige Anfrage, und alles andere passiert im Inneren der Datenbank (da Subquerys sich direkt in Native SQL übersetzen lassen).
Das ist ein guter Rat, weil so die gesamte Logik in der DB liegt und deren Optimizer dann den günstigsten Zugriffspfad wählen kann.
Theory is when you know something, but it doesn't work.
Practice is when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't know why.

ECC: 6.07
Basis: 7.40

Re: Alternative For All Entries

Beitrag von DeathAndPain (Top Expert / 1012 / 115 / 223 ) » 13. Feb 2019 09:51

{FOR ALL ENTRIES vs RANGES-Tabelle}
Doch, performancemäßig bringt das einiges, weil die Werte an die Datenbank in viel größeren Paketen übergeben werden können. Z.b. unter Oracle, wo die Übergabe bei FOR ALL ENTRIES ja standardmäßig mit nur 5 eingestellt ist.
Nicht "defaultmäßig", sondern das ist die von der SAP empfohlene Einstellung für Oracle. Der Grund für diese Empfehlung (bzw. generell dafür, weshalb es da überhaupt einen Grenzwert gibt) wird irgendwo in den SAP-Hinweisen auch erwähnt: Ab einer gewissen Menge übergebener Einzelwerte entscheidet sich die Optimierer der Datenbank nicht mehr dafür, den Index zu verwenden, sondern rast sequenziell durch die Tabelle, um auf diese Weise alle angefragten Einzelwerte abzugrasen. Offenbar ist dies jedoch deutlich ineffizienter, als für jeden Einzelwert den Index zu nutzen, weswegen es besser ist, die FOR ALL ENTRIES-Anfrage in so viele Teilanfragen aufzuteilen, dass der Optimierer jede einzelne, mit dem IN-Operator übertragene Teilanfrage noch über den Index abwickelt. Mit anderen Worten: SAP hat Gründe, weshalb sie das so empfehlen.

RANGES gibt es in Native SQL genauso wenig wie FOR ALL ENTRIES IN. ABAP hat also gar keine andere Wahl, als eine RANGES-Tabelle auch in passende Native SQL-Statements für die Datenbank zu übersetzen. Und dabei gibt es zwei Möglichkeiten: Entweder ABAP hält sich auch dabei an die Systemparameter, was dann zum FOR ALL ENTRIES IN äquivalent wäre, oder es beachtet die Systemparameter nicht, dann gibt es datenbankseitig einen sequenziellen Scan ohne Index, was aus Performancesicht die schlechtmöglichste Lösung ist.

Du kannst hier also nichts gewinnen, sondern bestenfalls nichts verlieren.

Re: Alternative For All Entries

Beitrag von black_adept (Top Expert / 3217 / 54 / 559 ) » 13. Feb 2019 11:46

Nur als Ergänzung ( nicht als Vorschlag zur Vorgehensweise, da ich das noch nicht ausgiebig getestet habe ): Ab irgend einem Release hat SAP die "global temporary tables" eingeführt. Eventuell könnte man die statt des FOR ALL ENTRIES verwenden.

Folgende Benutzer bedankten sich beim Autor black_adept für den Beitrag:
a-dead-trousers

live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Re: Alternative For All Entries

Beitrag von a-dead-trousers (Top Expert / 3199 / 81 / 792 ) » 14. Feb 2019 09:09

black_adept hat geschrieben:Ab irgend einem Release hat SAP die "global temporary tables" eingeführt. Eventuell könnte man die statt des FOR ALL ENTRIES verwenden.
Nice 8)
Theory is when you know something, but it doesn't work.
Practice is when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't know why.

ECC: 6.07
Basis: 7.40

Seite 1 von 2 (current) Nächste

Aktuelle Forenbeiträge

OBN im NWBC ohne Popup
vor 7 Stunden von msfox 2 / 37
Business Partner Konzept
vor 8 Stunden von waltersen 4 / 267
Exception Handling FuBa test
vor 10 Stunden von czschunke 2 / 88
MD14 Felder einblenden Umsetzung Planauftrag
vor 11 Stunden von Thomas R. 1 / 20

Unbeantwortete Forenbeiträge

MD14 Felder einblenden Umsetzung Planauftrag
vor 11 Stunden von Thomas R. 1 / 20
Verursachervormerkung OCM manuell anlegen
vor einer Woche von Aba 1 / 129
Auflösen MILL_OC - Auftragszusammenfassung
vor einer Woche von tofralu 1 / 112
Löschen von archivierten Drucklisten
vor einer Woche von Asaph 1 / 103