Sto costruendo una vista in SQL Server 2000 (e 2005) e ho notato che l'ordine delle istruzioni di join influenza notevolmente il piano di esecuzione e la velocità della query.Perché le clausole order of join influiscono sul piano di query in SQL Server?
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
in SQL Server 2000, la query sopra costantemente genera un piano di costo 946. Se io Rimuovere il commento dalla MO_Stream unirsi nel mezzo della query e commentare out quella in basso, il costo scende a 263. La velocità di esecuzione diminuisce di conseguenza. Ho sempre pensato che Query Optimizer avrebbe interpretato la query in modo appropriato senza considerare l'ordine di join, ma sembra che l'ordine sia importante.
Quindi, poiché l'ordine fa sembra avere importanza, c'è una strategia di join che dovrei seguire per scrivere query più veloci?
(Per inciso, in SQL Server 2005, con i dati quasi identici, i costi del piano di query erano 0,675 e 0,631, rispettivamente).
Edit: in SQL Server 2000, ecco le statistiche profilati:
946-cost query: 9094ms CPU, 5121 reads, 0 writes, 10123ms duration
263-cost query: 172ms CPU, 7477 reads, 0 writes, 170ms duration
Modifica: Ecco la struttura logica delle tabelle.
SessionRange ---+--- SessionRangeTutor
|--- SessionRangeClass
|--- SessionRangeStream --- MO_Stream
|--- SessionRangeEnrolmentPeriod
|--- SessionRangeStudent
+----SessionSubrange --- SessionSubrangeRoom
Edit: Grazie a Alex e gbn per avermi nella giusta direzione. Ho anche trovato this question.
Ecco la nuova query:
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
costo SQLServer2000: 24,9
Dipende dalla struttura delle tabelle. Hai ragione per il caso T1-T2, T2-T3. Nella mia situazione sono T1-T2, T1-T3. – geofftnz
@geofftnz: vedere la mia risposta. Tu sei * non * T1-T2, T1-T3 – gbn