2012-03-29 2 views
12

Mein google-fu und so-fu versagt mich hier, also könnte ich auch fragen.TSQL - Was ist die richtige Reihenfolge für das Verbinden von Tabellen?

Ich habe viele Abfragen mit mehreren Joins in ihnen.

Innerhalb einer Abfrage, bin ich header/item/details zusammen, sowie Nachschlagen verschiedener Informationen für diese Datensätze.

Wenn ich mich verbinde, versuche ich, die Dinge in der Reihenfolge ihrer Beziehung zu halten. Zum Beispiel: Meine Kopfzeile hat zwei Nachschlagetabellen, also werde ich mich mit denen verbinden, bevor ich mich meiner Gegenstandstabelle anschließe.

Ist das korrekt?

Ist es besser, zu größeren Tabellen vor Lookup-Tabellen zu verbinden? Oder umgekehrt?

Sollte ich einen loop Hinweis bei der Verbindung zu kleinen Tabellen verwenden, und einen merge Hinweis bei der Verbindung zu Openrowsets?

Ich bin sicher, die Antwort ist "es kommt darauf an", aber einige allgemeine Richtlinien zum effektiven und effizienten Beitritt wären sehr hilfreich. Vielen Dank!

+0

In den meisten Fällen sollten Sie den Join-Typ (merge/loop/hash) nicht angeben müssen. Wenn Sie es tun, gibt es wahrscheinlich zugrunde liegende Probleme, die anstelle der Join Hinweis Band-Hilfe gelöst werden sollten. –

+2

Wenn Sie nicht genau wissen, was Sie tun, und Sie die Abfrageausführungspläne verstehen, verwenden Sie NIE Abfragehinweise. – JotaBe

Antwort

12

EDIT: Basierend auf Ihren Fragen (und Kirk Woll) Kommentar, sollten Sie verstehen, dass die order of your joins is aesthetic, and does not directly impact the resulting execution plan. Der Abfrageoptimierer führt die Joins in der effizientesten Reihenfolge aus und verwendet die entsprechende Join-Operation die meiste Zeit ohne Hinweise.

Wenn es um die Ästhetik Ihrer Join-Reihenfolge geht, ist dies ein wenig subjektiv, aber ich würde sagen, verbinden Sie Ihre Tabellen in beliebiger Reihenfolge logisch sinnvoll beim Lesen der Abfrage ... wenn Sie mit einer @HeaderId beginnen, beginne mit dieser Tabelle und dann JOIN die Kindern Tabellen:

FROM 
    Header h 
    JOIN Items i ON h.HeaderId = i.HeaderId 
    JOIN Details d ON i.ItemId = d.ItemId 
WHERE 
    h.HeaderId = @HeaderId 

Aber, wenn Sie Ihre Abfrage mit einem @DetailId beginnen, würde ich in der umgekehrten Reihenfolge verbinden.

FROM 
    Details d 
    JOIN Items i ON d.ItemId = i.ItemId 
    JOIN Header h ON i.HeaderId = h.HeaderId 
WHERE 
    d.DetailId = @DetailId 

Aber das ist subjektiv und nur meine persönliche Vorliebe.

Es wird weniger subjektiv, wenn Sie anfangen, OUTER JOIN s einzuschließen ... versuchen Sie, Ihre Abfrage zu strukturieren, um irgendwelche RIGHT OUTER JOIN s zu vermeiden, und stattdessen LEFT OUTER JOIN 's zu verwenden.

Verwenden Sie keine Join-Hinweise standardmäßig ... in der Tat werden Sie fast nie sie verwenden. Der Abfrageoptimierer kann sehr gut den optimalen Ausführungsplan auswählen. Ich habe nur eine einzige Instanz gefunden, bei der ich einen Join-Hinweis zur Verbesserung des Plans angeben musste ... das hat auf dem Server, auf dem die Abfrage ausgeführt wurde, drastisch geholfen, aber wenn die Datenbank auf einen anderen Server migriert wurde, mein Join Hinweis zerstört die Leistung der Abfrage. Um dies zu wiederholen, ist es normalerweise eine schlechte Idee, Join-Hinweise zur Verfügung zu stellen.

+1

Vielleicht ist dem OP nicht bewusst, dass die Join-Reihenfolge für den Ausführungsplan irrelevant ist und rein ästhetisch ist? –

+0

@KirkWoll Das ist ein sehr guter Punkt, den ich übersehen habe ... Ich werde das in meiner Antwort klären. –

+0

@Kirk, genau darum frage ich. Die Reihenfolge ist überhaupt nicht relevant? – IronicMuffin

0

Die Reihenfolge ist weitgehend [1] ästhetisch, aber ich denke, es ist sinnvoll, eine Konvention für die Reihenfolge der Tabellen und die Bedingungen in den ON-Bedingungen zu haben, um Verwirrung zu vermeiden.

Abfragehinweise sind nur für Ausnahmefälle, und obwohl Sie Situationen finden können, in denen Sie sie verwenden müssen (in der Regel Leistungseinbußen für reduzierte Nebenläufigkeitsprobleme), sollten Sie immer versuchen, eine robustere Methode zur Behebung des Problems zu finden.

[1] Ich weiß von einem Fall, in dem die Reihenfolge keine Rolle spielt:

CREATE TABLE A (
    id int IDENTITY PRIMARY KEY, 
    name varchar 
); 

CREATE TABLE B (
    id int IDENTITY PRIMARY KEY, 
    a_id int FOREIGN KEY REFERENCES A (id), 
    name varchar 
); 

SELECT * 
FROM A 
INNER LOOP JOIN B on A.id = B.a_id; 

SELECT * 
FROM B 
INNER LOOP JOIN A on A.id = B.a_id; 

Die erste Auswahl macht zwei Index-Scans, die zweite hat einen Scan und suchen. Dies ist ein weiterer guter Grund, Hinweise zu vermeiden.

Verwandte Themen