Я создаю представление в SQL Server 2000 (и 2005), и я заметил, что порядок операторов соединения сильно влияет на план выполнения и скорость запроса.Почему порядок предложений соединения влияет на план запроса в 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
В SQL Server 2000, запрос выше последовательно формирует план стоимости 946. Если я раскомментировать MO_Stream присоединиться к середине запроса и закомментируйте один на дне, стоимость снижается до 263. Скорость выполнения соответственно уменьшается. Я всегда думал, что оптимизатор запросов будет интерпретировать запрос соответствующим образом, не рассматривая порядок объединения, но кажется, что порядок имеет значение.
Так как заказ делает, кажется, имеет значение, есть ли стратегия объединения, которую я должен соблюдать для написания более быстрых запросов?
(Кстати, на SQL Server 2005, с почти идентичными данными, затраты на плане запроса были 0,675 и 0,631 соответственно.)
Edit: В SQL Server 2000, здесь профилированные статистики:
946-cost query: 9094ms CPU, 5121 reads, 0 writes, 10123ms duration
263-cost query: 172ms CPU, 7477 reads, 0 writes, 170ms duration
Редактировать: Вот логическая структура таблиц.
SessionRange ---+--- SessionRangeTutor
|--- SessionRangeClass
|--- SessionRangeStream --- MO_Stream
|--- SessionRangeEnrolmentPeriod
|--- SessionRangeStudent
+----SessionSubrange --- SessionSubrangeRoom
Edit: Благодаря Алексу и ГБН указал мне в правильном направлении. Я также нашел this question.
Вот новый запрос:
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 Стоимость: 24,9
Это зависит от структуры таблиц. Вы верны для случая T1-T2, T2-T3. В моей ситуации это T1-T2, T1-T3. – geofftnz
@geofftnz: см. Мой ответ. Вы не * T1-T2, T1-T3 – gbn