Warum spielt die Reihenfolge der join-Klauseln betreffen den Abfrageplan in SQL Server?

Baue ich eine Ansicht in SQL Server 2000 (und 2005) und ich habe bemerkt, dass die Reihenfolge der join-Anweisungen beeinflusst die Ausführung planen und die Geschwindigkeit der Abfrage.

select      sr.WTSASessionRangeID,
            -- bunch of other columns
from        WTSAVW_UserSessionRange us
inner join  WTSA_SessionRange sr on sr.WTSASessionRangeID = us.WTSASessionRangeID
left outer join WTSA_SessionRangeTutor srt on srt.WTSASessionRangeID = sr.WTSASessionRangeID
left outer join WTSA_SessionRangeClass src on src.WTSASessionRangeID = sr.WTSASessionRangeID
left outer join WTSA_SessionRangeStream srs on srs.WTSASessionRangeID = sr.WTSASessionRangeID
--left outer join MO_Stream ms on ms.MOStreamID = srs.MOStreamID
left outer join WTSA_SessionRangeEnrolmentPeriod srep on srep.WTSASessionRangeID = sr.WTSASessionRangeID
left outer join WTSA_SessionRangeStudent stsd on stsd.WTSASessionRangeID = sr.WTSASessionRangeID
left outer join WTSA_SessionSubrange ssr on ssr.WTSASessionRangeID = sr.WTSASessionRangeID
left outer join WTSA_SessionSubrangeRoom ssrr on ssrr.WTSASessionSubrangeID = ssr.WTSASessionSubrangeID
left outer join MO_Stream ms on ms.MOStreamID = srs.MOStreamID

Auf SQL Server 2000, die obige Abfrage generiert kontinuierlich einen plan, der Kosten-946. Wenn ich die Auskommentierung der MO_Stream sich in der Mitte der Abfrage und kommentieren Sie die ein an der Unterseite, die Kosten Tropfen auf 263. Die Ausführungsgeschwindigkeit sinkt entsprechend. Ich dachte immer, dass der query optimizer würde die Abfrage interpretieren entsprechend ohne Berücksichtigung der join-Reihenfolge, aber es scheint, die Reihenfolge ist wichtig.

Also da, um hat scheint es, gibt es eine join-Strategie sollte ich für das schreiben schneller Abfragen?

(Übrigens auf SQL Server 2005 mit fast identischen Daten, der Abfrage-plan wurden die Kosten 0.675 und 0.631 werden.)

Edit: Auf SQL Server 2000, hier sind die profilierten stats:

  • 946-cost query: 9094ms CPU, 5121 reads, 0 writes, 10123ms duration
  • 263-cost query: 172ms CPU, 7477 reads, 0 writes, 170ms duration

Edit: Hier wird die logische Struktur der Tabellen.

SessionRange ---+--- SessionRangeTutor
                |--- SessionRangeClass
                |--- SessionRangeStream --- MO_Stream
                |--- SessionRangeEnrolmentPeriod
                |--- SessionRangeStudent
                +----SessionSubrange --- SessionSubrangeRoom

Edit: vielen Dank an Alex und gbn für den Hinweis mich in die richtige Richtung. Ich fand auch diese Frage.

Hier ist das neue-Abfrage:

select sr.WTSASessionRangeID    // + lots of columns

from WTSAVW_UserSessionRange us
inner join WTSA_SessionRange sr on sr.WTSASessionRangeID = us.WTSASessionRangeID
left outer join WTSA_SessionRangeTutor srt on srt.WTSASessionRangeID = sr.WTSASessionRangeID
left outer join WTSA_SessionRangeClass src on src.WTSASessionRangeID = sr.WTSASessionRangeID
left outer join WTSA_SessionRangeEnrolmentPeriod srep on srep.WTSASessionRangeID = sr.WTSASessionRangeID
left outer join WTSA_SessionRangeStudent stsd on stsd.WTSASessionRangeID = sr.WTSASessionRangeID

// SessionRangeStream is a many-to-many mapping table between SessionRange and MO_Stream
left outer join (
    WTSA_SessionRangeStream srs
    inner join MO_Stream ms on ms.MOStreamID = srs.MOStreamID
) on srs.WTSASessionRangeID = sr.WTSASessionRangeID

// SessionRanges MAY have Subranges and Subranges MAY have Rooms
left outer join (
    WTSA_SessionSubrange ssr    
    left outer join WTSA_SessionSubrangeRoom ssrr on ssrr.WTSASessionSubrangeID = ssr.WTSASessionSubrangeID
) on ssr.WTSASessionRangeID = sr.WTSASessionRangeID

SQLServer2000 Kosten: 24.9

InformationsquelleAutor geofftnz | 2009-07-28
Schreibe einen Kommentar