Reihenfolge Join

R_007

Benutzer
Beiträge
5
Hallo,

ich habe eine Frage zu dem Join von mehreren Tabellen. Wenn ich zwei Tabellen bspw. einen left join habe, ist es ja ganz einfach. Dann werden aus der linken Tabelle alle Sätze genommen und die passenden aus der rechten dran gejoint.

Wie ist das bei nachfolgendem Beispiel, wenn ich mehrere Joins habe - insbesondere bei dem Join der Tabelle_4 and die Tabelle_2. Wird dort erst die Tabelle 1 mit 2 gejoint und das Ergebnis dann left outer an die Tabelle 4?

select *
from
Tabelle_1
left join Tabelle_2 on Tabelle_1.X = Tabelle_2.X
join Tabelle_3 on Tabelle_2.X = Tabelle_3.X
left join Tabelle_4 on Tabelle_4.X = Tabelle_2.X

Wenn ich die Join-Logik umdrehe wird es noch etwas komplizierter. Ich habe die left joins durch right joins getauscht und jetzt ist es ja ein Unterschied, ob ich erst die Tabelle_1 mit 2 right joine oder erst Tabelle_2 mit 4 right joine und dann das Ergebnis mit Tabelle_1.

select *
from
Tabelle_1
right join Tabelle_2 on Tabelle_1.X = Tabelle_2.X
join Tabelle_3 on Tabelle_2.X = Tabelle_3.X
right join Tabelle_4 on Tabelle_4.X = Tabelle_2.X

Gibt es irgendeine Seit wo diese Probleme anhand von Beispielen erklärt sind?

Gruß
R_007
 
Werbung:
Ein "Problem" gibt es ja eigentlich nicht, gejoint wird in der Reihenfolge wie es da steht. Nirgendwo steht geschrieben das mehrere Joins, unabhängig von ihrer Reihenfolge, die selben Ergebnisse liefern.
 
Aber wird dann erst Tabelle1 mit 2 gejoint und anschließend das Ergebnis mit Tabelle4? Das wären dann ja in der Reihenfolge.
 
Gibt es irgendeine Seit wo diese Probleme anhand von Beispielen erklärt sind?

Die Syntax mit den JOIN-Conditions gibt an, wie die Tabellen logisch zusammengehören. In welcher Reichenfolge die JOINs dastehen ist egal - die DB ist eh frei, diese Reihenfolge so zu gestalten, daß die Performance möglichst gut ist. (das geht fast immer). Irgendwann kommt aber der Moment, wo sehr, sehr viele Joins involviert sind, dann dann wird die Berechnung der optimalen Reihenfolge immer aufwendiger, da alle möglichen Kombinationen auf ihre Kosten durchgerechnet werden. In PostgreSQL kannst Du das steuern, via join_collapse_limit.

Falls noch mehr Joins involviert sind, tritt (bei PostgreSQL) ein 'generic query optimizer' an den Start, um die Planungszeit zu reduzieren. Das ist per Default z.B. bei 12 der Fall.
 
Danke für die Antwort! Aber wird dann erst Tabelle1 mit 2 gejoint und anschließend das Ergebnis mit Tabelle4? Das wären dann ja in der Reihenfolge.
 
Danke für den Link, ist sehr interessant nur leider hilft er mir nur teilweise weiter meine im vorherigen Post gestellte Frage zu beantworten. Hat von euch einer ne Idee was die Antwort auf die Frage ist?
 
Die Frage ist so leicht nicht zu beantworten. Ich habe mal tabelle_1 bis tabelle_4 erzeugt (immer nur eine INT-Spalte x) und und in jeder die zahlen 1 bis 10 drin. Der Ausführungsplan für left join sieht dann so aus:

Code:
test=# explain select *   
from
Tabelle_1
left join Tabelle_2 on Tabelle_1.X = Tabelle_2.X
join Tabelle_3 on Tabelle_2.X = Tabelle_3.X
left join Tabelle_4 on Tabelle_4.X = Tabelle_2.X;
  QUERY PLAN   
----------------------------------------------------------------------------------
 Hash Left Join  (cost=3.68..5.19 rows=10 width=16)
  Hash Cond: (tabelle_2.x = tabelle_4.x)
  ->  Hash Join  (cost=2.45..3.83 rows=10 width=12)
  Hash Cond: (tabelle_1.x = tabelle_3.x)
  ->  Hash Join  (cost=1.23..2.46 rows=10 width=8)
  Hash Cond: (tabelle_1.x = tabelle_2.x)
  ->  Seq Scan on tabelle_1  (cost=0.00..1.10 rows=10 width=4)
  ->  Hash  (cost=1.10..1.10 rows=10 width=4)
  ->  Seq Scan on tabelle_2  (cost=0.00..1.10 rows=10 width=4)
  ->  Hash  (cost=1.10..1.10 rows=10 width=4)
  ->  Seq Scan on tabelle_3  (cost=0.00..1.10 rows=10 width=4)
  ->  Hash  (cost=1.10..1.10 rows=10 width=4)
  ->  Seq Scan on tabelle_4  (cost=0.00..1.10 rows=10 width=4)
(13 Zeilen)

dann habe ich in Tabelle_4 eingefügt:

Code:
test=*# insert into tabelle_4 select * from generate_series(1,1000000) a;
INSERT 0 1000000

Der Plan ist nun, trotz gleicher Abfrage, ein anderer:

Code:
test=*# explain select *
from
Tabelle_1
left join Tabelle_2 on Tabelle_1.X = Tabelle_2.X
join Tabelle_3 on Tabelle_2.X = Tabelle_3.X
left join Tabelle_4 on Tabelle_4.X = Tabelle_2.X;
  QUERY PLAN   
-------------------------------------------------------------------------------------
 Nested Loop  (cost=1.23..18181.71 rows=10 width=16)
  Join Filter: (tabelle_1.x = tabelle_3.x)
  ->  Nested Loop  (cost=1.23..18179.09 rows=10 width=12)
  Join Filter: (tabelle_2.x = tabelle_1.x)
  ->  Hash Right Join  (cost=1.23..18176.46 rows=10 width=8)
  Hash Cond: (tabelle_4.x = tabelle_2.x)
  ->  Seq Scan on tabelle_4  (cost=0.00..14425.10 rows=1000010 width=4)
  ->  Hash  (cost=1.10..1.10 rows=10 width=4)
  ->  Seq Scan on tabelle_2  (cost=0.00..1.10 rows=10 width=4)
  ->  Materialize  (cost=0.00..1.15 rows=10 width=4)
  ->  Seq Scan on tabelle_1  (cost=0.00..1.10 rows=10 width=4)
  ->  Materialize  (cost=0.00..1.15 rows=10 width=4)
  ->  Seq Scan on tabelle_3  (cost=0.00..1.10 rows=10 width=4)
(13 Zeilen)


Wenn Dich das Thema interessiert, so installier Dir einfach PostgreSQL und schau, wie es arbeitet.
 
R_007 geht davon aus, das das Ergebnis des Joins je nach Reihenfolge der Joins ein Anderes ist. Wenn ich darüber nachdenke glaube ich allerdings, das da immer das Selbe raus kommen müsste. Es muss natürlich so gejoint werden, das die Spalten in der Join-Condition alle bekannt sind, der Rest ist egal.
 
Zuletzt bearbeitet:
Werbung:
Ich meinte eigentlich das das Ergebnis gleich ist egal in welcher Reihenfolge du joinst. Nur wenn du mit Spalten aus einem Join in der Join-Condition weiter arbeiten musst, also z.B. Tabelle 3 auf eine Spalte in Tabelle 2 joinst, musst du natürlich in der Reihenfolge bleiben. Wenn du aber sowohl Tabelle 2 als auch Tabelle 3 auf eine Spalte in Tabelle 1 joinst, ist das Ergebnis das Selbe, egal welcher Join zuerst statt findet.
 
Zurück
Oben