DB-Tabellen verknüpfen: Was ist am performantesten?

Alles rund um die Sprache ABAP®: Funktionsbausteine, Listen, ALV
17 Beiträge • Seite 1 von 2 (current) Nächste
17 Beiträge Seite 1 von 2 (current) Nächste

DB-Tabellen verknüpfen: Was ist am performantesten?

Beitrag von DeathAndPain (Top Expert / 1939 / 257 / 412 ) »
Hallo zusammen,

hier mal wieder ein eher akademisches Problem, wobei ich es schon nicht schlecht fände, den besten Weg in der Praxis zu kennen. Es geht darum, in einem SELECT zwei Tabellen über ein Schlüsselfeld miteinander zu verbinden. Dafür sehe ich drei naheliegende Lösungsansätze (daneben wird es womöglich noch schrägere geben, denen ich aber wenig Chancen auf die Performancekrone einräume):
  • einen klassischen INNER JOIN
  • eine Subquery mit IN
  • eine Subquery mit EXISTS
Alle drei SELECTs liefern die gleiche Ergebnismenge. Ich habe ein Testprogramm geschrieben, das alle drei Varianten durchprobiert und die Laufzeiten vergleicht. Der vollständige Code ist hier:

Code: Alles auswählen.

*&---------------------------------------------------------------------*
*& Report ZTEST_TABLE_SEARCH
*&---------------------------------------------------------------------*
REPORT ZTEST_TABLE_SEARCH2.

DATA: T_OBJID TYPE STANDARD TABLE OF HROBJID WITH HEADER LINE,
      I TYPE I,
      J TYPE I,
      RUNTIME TYPE I.

PARAMETERS: JN_FIRST RADIOBUTTON GROUP ONE,
            SB_FIRST RADIOBUTTON GROUP ONE,
            EX_FIRST RADIOBUTTON GROUP ONE.

*** START-OF-SELECTION ***
START-OF-SELECTION.

  CASE 'X'.
    WHEN JN_FIRST.
      PERFORM SELECT_WITH_JOIN.
      WRITE: / 'Join:', RUNTIME, 'microseconds'.
      WRITE: / LINES( T_OBJID ), 'table entries'.
      PERFORM SELECT_WITH_SUBQUERY.
      WRITE: / 'Subquery:', RUNTIME, 'microseconds'.
      WRITE: / LINES( T_OBJID ), 'table entries'.
      PERFORM SELECT_WITH_EXISTS.
      WRITE: / 'Exists-Clause:', RUNTIME, 'microseconds'.
      WRITE: / LINES( T_OBJID ), 'table entries'.
    WHEN SB_FIRST.
      PERFORM SELECT_WITH_SUBQUERY.
      WRITE: / 'Subquery:', RUNTIME, 'microseconds'.
      WRITE: / LINES( T_OBJID ), 'table entries'.
      PERFORM SELECT_WITH_JOIN.
      WRITE: / 'Join:', RUNTIME, 'microseconds'.
      WRITE: / LINES( T_OBJID ), 'table entries'.
      PERFORM SELECT_WITH_EXISTS.
      WRITE: / 'Exists-Clause:', RUNTIME, 'microseconds'.
      WRITE: / LINES( T_OBJID ), 'table entries'.
    WHEN EX_FIRST.
      PERFORM SELECT_WITH_EXISTS.
      WRITE: / 'Exists-Clause:', RUNTIME, 'microseconds'.
      WRITE: / LINES( T_OBJID ), 'table entries'.
      PERFORM SELECT_WITH_SUBQUERY.
      WRITE: / 'Subquery:', RUNTIME, 'microseconds'.
      WRITE: / LINES( T_OBJID ), 'table entries'.
      PERFORM SELECT_WITH_JOIN.
      WRITE: / 'Join:', RUNTIME, 'microseconds'.
      WRITE: / LINES( T_OBJID ), 'table entries'.
  ENDCASE.

*&---------------------------------------------------------------------*
*&      Form  SELECT_WITH_JOIN
*&---------------------------------------------------------------------*
FORM SELECT_WITH_JOIN.
  GET RUN TIME FIELD I.
  SELECT OBJID INTO TABLE T_OBJID FROM PA0001
    JOIN HRP1001 ON HRP1001~SOBID = PA0001~PERNR
   WHERE PA0001~WERKS = 'Z001'
     AND PA0001~BEGDA <= SY-DATUM
     AND PA0001~ENDDA >= SY-DATUM.
  GET RUN TIME FIELD J.
  RUNTIME = J - I.
ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  SELECT_WITH_SUBQUERY
*&---------------------------------------------------------------------*
FORM SELECT_WITH_SUBQUERY.
  GET RUN TIME FIELD I.
  SELECT OBJID INTO TABLE T_OBJID FROM HRP1001
   WHERE SOBID IN ( SELECT PERNR FROM PA0001
                     WHERE WERKS = 'Z001'
                       AND PA0001~BEGDA <= SY-DATUM
                       AND PA0001~ENDDA >= SY-DATUM ).
  GET RUN TIME FIELD J.
  RUNTIME = J - I.
ENDFORM.

*&---------------------------------------------------------------------*
*&      Form  SELECT_WITH_EXISTS
*&---------------------------------------------------------------------*
FORM SELECT_WITH_EXISTS.
  GET RUN TIME FIELD I.
  SELECT OBJID INTO TABLE T_OBJID FROM HRP1001
   WHERE EXISTS ( SELECT PERNR FROM PA0001
                     WHERE PERNR = HRP1001~SOBID
                       AND WERKS = 'Z001'
                       AND PA0001~BEGDA <= SY-DATUM
                       AND PA0001~ENDDA >= SY-DATUM ).
  GET RUN TIME FIELD J.
  RUNTIME = J - I.
ENDFORM.
Selektionstexte:
Bild

Der Code ist für ein HCM-System ausgelegt. Zum Ausprobieren auf einem anderen System müssen in den drei Formroutinen am Schluss die Datenbanktabellen HRP1001 und PA0001 durch solche ersetzt werden, die auf dem betreffenden System gut gefüllt sind (z.B. MARA und MARC). Außerdem sei mir verziehen, dass ich aus Faulheitsgründen mit globalen Variablen arbeite; der Gesamtcode ist keine 100 Zeilen lang und extrem übersichtlich.

Es fällt auf, dass die Performance sehr stark davon abhängt, welcher SELECT zuerst ausgeführt wird (weswegen das Programm es erlaubt, dies zu variieren). Außerdem kommen serverlastbedingte Schwankungen hinzu. Man muss es also oft starten, um ein Gefühl dafür zu bekommen. Mein subjektiver Eindruck ist, dass der JOIN geringfügig schlechter performt und die anderen beiden in etwa auf Augenhöhe sind, vielleicht mit einem minimalen Vorteil für den EXISTS - aber das kann auch Einbildung sein.

Dass nach der ersten Programmausführung die Datenbank ihre Caches vollgeladen hat und man dann nur noch Werte von dort bekommt, ist natürlich nicht hilfreich.

Wie geht man da jetzt am besten vor? Welcher SELECT ist der beste?

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


Re: DB-Tabellen verknüpfen: Was ist am performantesten?

Beitrag von black_adept (Top Expert / 4087 / 126 / 940 ) »
Kurze pragmatische Hinweise.
  • Kannst du mit "BYPASSING BUFFER" nicht den Cache überlisten um eine bessere Messgenauigkeit zu erzielen
  • Wenn die Laufzeit nur "gefühlt" unterschiedlich ist und du mehrere Anläufe unternehmen musst um evtl. einen Unterschied zu bemerken - ist es dann nicht egal welche der Varianten du verwendest?
  • Wenn alle Laufzeiten im grünen Bereich sind: Nimm den lesbarsten
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Re: DB-Tabellen verknüpfen: Was ist am performantesten?

Beitrag von DeathAndPain (Top Expert / 1939 / 257 / 412 ) »
Kannst du mit "BYPASSING BUFFER" nicht den Cache überlisten um eine bessere Messgenauigkeit zu erzielen
"BYPASSING BUFFER" bezieht sich meines Wissens nur auf die SAP-seitige Pufferung, die in der SE11 im Bereich "Technische Einstellungen" der Tabelle definiert ist. Große Tabellen (wie die hier von mir verwendeten) haben hier normalerweise "Pufferung nicht erlaubt" zu stehen, was bedeutet, dass die SAP-Pufferung für sie sowieso nicht aktiv ist.

Daneben cachen die Datenbanken aber auch noch selber, so dass kurz aufeinanderfolgende Zugriffe auf dieselbe Tabelle erheblich beschleunigt werden. Ich wüsste nicht, wie sich das aus ABAP verhindern ließe.
Wenn die Laufzeit nur "gefühlt" unterschiedlich ist und du mehrere Anläufe unternehmen musst um evtl. einen Unterschied zu bemerken - ist es dann nicht egal welche der Varianten du verwendest?
Mein Beispiel ist ja relativ willkürlch gewählt, und auf dem Entwicklungssystem haben wir auch nicht mal annähernd so viel Daten. Ich wollte den Report aber als lokales Objekt ohne Transport machen, so dass ich ihn in den Folgesystemen nicht ausprobieren kann. Außerdem ist das ja nur ein einziger SELECT. Den fühlt man selten. In produktiven Programmen läppert sich das aber, je nachdem, ob man immer eine effiziente oder immer eine ineffiziente Codingweise verwendet. Auch wenn es hier nicht viel ausmacht: wenn Du alle Deine Datenbankzugriffe 5% schneller machen könntest, nur durch eine andere Art und Weise, Dein Statement zu schreiben (aber auf eine vergleichbar gut lesbare Art und Weise), würdest Du das nicht gerne als kleinen, aber kostenlosen Bonus mitnehmen? Deswegen würde ich das halt gerne einmal klären, welcher Ansatz der performanteste ist und mir den dann (ohne Nachteile) angewöhnen. Nur laufe ich halt in das Problem der nicht allzu vollen Datenbank im Entwicklungssystem und des Datenbank-Cachings.
Wenn alle Laufzeiten im grünen Bereich sind: Nimm den lesbarsten
Schau Dir die SELECTs an (in den drei kleinen Formroutinen ganz am Ende des Programms). Ist da einer bedeutend besser oder schlechter lesbar als der andere?

Re: DB-Tabellen verknüpfen: Was ist am performantesten?

Beitrag von ewx (Top Expert / 4844 / 311 / 640 ) »
Vergleiche sind immer interessant! ;)
Aber egal, was bei diesem speziellen Vergleich herauskommt, wirst du nicht pauschal sagen können: Variante X ist immer schneller, da es wahrscheinlich immer auf verschiedene Umstände ankommt:
- Anzahl der Datensätze in Tabelle 1
- Anzahl der Datensätze in Tabelle 2
- vorhandene (oder nicht vorhandene) Indizes
- Speicherbereich beider Tabellen in der DB
- Größe und Anzahl der Ergebnismenge
- ...

Es ist deswegen immer ratsam im Zweifel ein kleines Testprogramm zu schreiben.
Wenn du es in der ST05 oder SAT auswertest, kannst du ggfs. sogar noch detailliertere Infos bekommen.
Bei Sub-Queries gibt es leider keine weiteren Infos, so wie ich das gerade sehe.

Re: DB-Tabellen verknüpfen: Was ist am performantesten?

Beitrag von DeathAndPain (Top Expert / 1939 / 257 / 412 ) »
Aber egal, was bei diesem speziellen Vergleich herauskommt, wirst du nicht pauschal sagen können: Variante X ist immer schneller, da es wahrscheinlich immer auf verschiedene Umstände ankommt:
Im Prinzip richtig, aber wenn Du Dir meine SELECTs anschaust, dann wirst Du sehen, dass da im Prinzip dieselben Indizes genutzt werden, nur auf verschiedene Art und Weise. Natürlich kann es immer umständeabhängige Effekte geben. Es kann sogar sein, dass unter Oracle das eine Statement schneller ist und unter Sybase das andere. Ich wollte halt etwas Brainstorming haben, was man noch alles zur Entscheidungsfindung heranziehen könnte. Vielleicht fällt ja dem einen oder anderen zu den gewählten Ansätzen meiner drei SELECT-Statements was Ergänzendes ein.
Es ist deswegen immer ratsam im Zweifel ein kleines Testprogramm zu schreiben.
Rate mal, was ich gemacht habe. Oben im Ausgangsposting findest Du es, bereit für Copy & Paste in Dein Entwicklungssystem! ;-)

Re: DB-Tabellen verknüpfen: Was ist am performantesten?

Beitrag von ewx (Top Expert / 4844 / 311 / 640 ) »
DeathAndPain hat geschrieben:
Aber egal, was bei diesem speziellen Vergleich herauskommt, wirst du nicht pauschal sagen können: Variante X ist immer schneller, da es wahrscheinlich immer auf verschiedene Umstände ankommt:
Im Prinzip richtig, aber wenn Du Dir meine SELECTs anschaust, dann wirst Du sehen, dass da im Prinzip dieselben Indizes genutzt werden, nur auf verschiedene Art und Weise. Natürlich kann es immer umständeabhängige Effekte geben. Es kann sogar sein, dass unter Oracle das eine Statement schneller ist und unter Sybase das andere.
Ich meinte auch nicht deine drei SELECTS im Speziellen sondern irgendwelche anderen SELECTS mit anderen Tabellen.
Man darf halt anhand eines Beispiels nicht daherkommen und sagen: "SUB-QUERY schlägt INNER JOIN. Mach also lieber immer einen SUB-Query...!"
DeathAndPain hat geschrieben:Ich wollte halt etwas Brainstorming haben, was man noch alles zur Entscheidungsfindung heranziehen könnte. Vielleicht fällt ja dem einen oder anderen zu den gewählten Ansätzen meiner drei SELECT-Statements was Ergänzendes ein.
FOR ALL ENTRIES könnte man vielleicht noch prüfen. Das sind zwar dann zwei Selects aber das muss nicht schlechter sein.
DeathAndPain hat geschrieben:
Es ist deswegen immer ratsam im Zweifel ein kleines Testprogramm zu schreiben.
Rate mal, was ich gemacht habe. Oben im Ausgangsposting findest Du es, bereit für Copy & Paste in Dein Entwicklungssystem! ;-)
Ich habe dein Posting gelesen, bevor ich geantwortet habe...! ;)

Re: DB-Tabellen verknüpfen: Was ist am performantesten?

Beitrag von DeathAndPain (Top Expert / 1939 / 257 / 412 ) »
FOR ALL ENTRIES könnte man vielleicht noch prüfen. Das sind zwar dann zwei Selects aber das muss nicht schlechter sein.
Das wäre aber mehr als überraschend, wenn das performanter wäre. Zum einen liest Du damit eine Staffel Werte in den Hauptspeicher, die Du dort gar nicht brauchst, um sie anschließend an die Datenbank zurückzugeben, zum anderen ist bekannt, dass ABAP den FOR ALL ENTRIES in IN (..., ..., ...)-Klauseln umsetzt, bevor es sie an die Datenbank schickt. Dabei gibt es eine Obergrenze an Werten in dem IN-Statement, bevor ein neuer SELECT angefangen wird. Diese Obergrenze sitzt in einem Profilparameter und soll verhindern, dass der Datenbankoptimierer sich angesichts der vielen Einzelwerte für einen sequenziellen Zugriff entscheidet (der trotzdem deutlich schlechter wäre). Defaultmäßig beträgt dieser Wert bei Oracle nach meiner Erinnerung 5, bei Sybase immerhin 128. Das bedeutet, dass die Datenbank bei dieser Variante nicht nur die beiden von Dir angesprochenen SELECTs bekommt, sondern alle 5 bzw. 128 Tabelleneinträge einen weiteren. Das kann nie und nimmer so effizient sein, wie der Datenbank einen einzigen SELECT zu übergeben, der alle Informationen enthält, und sie dann eigenständig unter Nutzung ihrer eingebauten Optimierungsalgorithmen machen zu lassen.

Tja, und eine Argumentation wie diese würde ich mir jetzt auch wünschen, um meine drei Ansätze zu bewerten und den besten zu finden. Leider bekomme ich von denen von der Plausibilität aber keinen so leicht widerlegt wie den FOR ALL ENTRIES IN.

Re: DB-Tabellen verknüpfen: Was ist am performantesten?

Beitrag von Wann (ForumUser / 60 / 3 / 15 ) »
DeathAndPain hat geschrieben:
Mein Beispiel ist ja relativ willkürlch gewählt, und auf dem Entwicklungssystem haben wir auch nicht mal annähernd so viel Daten. Ich wollte den Report aber als lokales Objekt ohne Transport machen, so dass ich ihn in den Folgesystemen nicht ausprobieren kann.
Wenn ich so etwas mit ordentlichen Daten im Q-System überprüfen will, packe ich das in ein LSMW-Projekt. Das ist dann ganz fix getestet.

Re: DB-Tabellen verknüpfen: Was ist am performantesten?

Beitrag von DeathAndPain (Top Expert / 1939 / 257 / 412 ) »
Im Q-System habe ich umfassend Daten, aber im E-System nicht. Wir arbeiten hier aber mit dem Solution Manager (also nicht direkt mit der STMS für den Transport). Wenn ich aber nicht extra ein Solution Manager Ticket anlegen, daraus einen Change erzeugen, diesen genehmigen, daraus Transportaufträge erzeugen und das Testprogramm dann ins Q transportieren will, wissend, dass ich es im P nie werden haben wollen, dann greife ich lieber zu einem "lokalen Objekt" ohne Transportauftrag. Das aber kriege ich nicht ins Q geschoben.

Re: DB-Tabellen verknüpfen: Was ist am performantesten?

Beitrag von Wann (ForumUser / 60 / 3 / 15 ) »
Deshalb ja LSMW. In der Regel können dort LSMW-Projekte erstellt, geändert und/oder importiert/exportiert werden. Da wird kein Transport gebraucht.

Re: DB-Tabellen verknüpfen: Was ist am performantesten?

Beitrag von DeathAndPain (Top Expert / 1939 / 257 / 412 ) »
Mal abgesehen davon, dass die LSMW auch Grenzen hat: Das Verschieben von Daten zwischen Systemen ist hier nicht der Engpass, dafür gibt es im HCM das verbreitete Tool Clone&Test von Accenture. Die Sache ist aber die, dass produktive Daten nicht in ein Entwicklungssystem gehören. Auch nicht anonymisiert zum Testen; dafür ist das Testsystem da.

Re: DB-Tabellen verknüpfen: Was ist am performantesten?

Beitrag von black_adept (Top Expert / 4087 / 126 / 940 ) »
Lass dir mal das TestSystem aufmachen zur Entwicklung um dein Testprogramm dort kurz mal zu parken.
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Re: DB-Tabellen verknüpfen: Was ist am performantesten?

Beitrag von DeathAndPain (Top Expert / 1939 / 257 / 412 ) »
Dafür würden die hiesigen Auditoren mich aufknüpfen. Ich bin mir auch nicht sicher, ob es so einen großen Unterschied machen würde. Ich habe ja eine gewisse Datenmenge auch im Entwicklungssystem. Zwar nur rund 2000 Datensätze, aber immerhin. Ihr seid aber herzlich eingeladen, mein Testprogramm auf euren Systemen anzutesten (ggf. vorher die Tabellen durch bei euch gut gefüllte mit einer passenden Verknüpfungsbedingung (gemeinsames Schlüsselfeld) ersetzen).

Was ich im Moment mache, ist mein Testprogramm immer einmal am Tag mit einer anderen Reihenfolgen-Variante starten und das Ergebnis notieren. Das ist wenigstens ein Lesevorgang, der sich nicht auf den Datenbank-Cache stützen kann. Mal schauen, ob sich da ein Ergebnis herauskristallisiert, wenn ich das über Wochen hinweg mache. Ein einmaliger Lauf hat natürlich keine Aussagekraft, da in der Sekunde auf dem Server gerade irgendwas los gewesen sein kann (das sind ja immer virtuelle Maschinen, die sich die Hardware mit anderen teilen).

Re: DB-Tabellen verknüpfen: Was ist am performantesten?

Beitrag von ralf.wenzel (Top Expert / 3924 / 200 / 280 ) »
Tja, es gibt Dinge, die gehen einfach nicht. Ich habe in genug Projekten gearbeitet, in denen gern auch mal ein P aufgemacht wurde, weil das schneller ist als Transportiererei. Da finde ich eine gewisse Strenge schon gut. Klar, das behindert bei der Arbeit. Ich finde es auch nervig, Sicherungen ziehen zu müssen, ehe ich an der Elektrik arbeiten will. Geht ja auch ohne. Aber gerade ein Profi (Elektriker) arbeitet NIEMALS unter Spannung, das sind immer nur die Amateure, die sowas machen.


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

Re: DB-Tabellen verknüpfen: Was ist am performantesten?

Beitrag von Wann (ForumUser / 60 / 3 / 15 ) »
DeathAndPain hat geschrieben:Mal abgesehen davon, dass die LSMW auch Grenzen hat: Das Verschieben von Daten zwischen Systemen ist hier nicht der Engpass, dafür gibt es im HCM das verbreitete Tool Clone&Test von Accenture. Die Sache ist aber die, dass produktive Daten nicht in ein Entwicklungssystem gehören. Auch nicht anonymisiert zum Testen; dafür ist das Testsystem da.
15 Minuten. Länger dauert es nicht, Dein Programm in ein LSMW-Projekt zu packen und im Testsystem(Q) laufen zu lassen.

Vergleichbare Themen

10
Antw.
5290
Views
Tabellen verknüpfen
von bohne » 20.02.2007 08:52 • Verfasst in ABAP® für Anfänger
1
Antw.
1158
Views
Tabelllen verknüpfen
von Russel » 23.08.2005 08:09 • Verfasst in ABAP Objects®
4
Antw.
17329
Views
Zeichenketten verknüpfen
von Preacha » 06.08.2008 13:54 • Verfasst in ABAP® für Anfänger
7
Antw.
3336
Views
Tabllen verknüpfen!!!
von Russel » 23.08.2005 07:42 • Verfasst in ABAP® für Anfänger
0
Antw.
937
Views

Aktuelle Forenbeiträge

Zeilenumbrüche ersetzen
vor 19 Stunden von ralf.wenzel 6 / 169
Dialog-Container mit Toolbar/Status
Gestern von tar gelöst 19 / 2333
SAP Trial Version für SAP Fiori
vor 2 Tagen von tar 2 / 1547

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

Zeilenumbrüche ersetzen
vor 19 Stunden von ralf.wenzel 6 / 169
Dialog-Container mit Toolbar/Status
Gestern von tar gelöst 19 / 2333
SAP Trial Version für SAP Fiori
vor 2 Tagen von tar 2 / 1547

Unbeantwortete Forenbeiträge

Daten an Tabelle binden
vor 2 Tagen von Bright4.5 1 / 611
aRFC im OO-Kontext
vor 4 Wochen von ralf.wenzel 1 / 2238
Hilfe bei SWEC/SWE2
letzen Monat von retsch 1 / 8830