Я пишу хранимую процедуру, которая будет получать данные для отчета о продажах. Запросы выглядят так:
INSERT INTO @FirstQuery
SELECT t1.*, t2.*
FROM t1
LEFT JOIN t2 ON t1.idT1 = t2.idT1
LEFT JOIN t3 ON t3.idT2 = t2.idT2
WHERE t1.nonIndexedField = @parameter1
AND (t2.idT2 IS NULL
OR
(@parameter2 = 'XXX' AND t1.indexedField1 = @parameter3)
OR
(@parameter2 = 'YYY' AND t3.indexedField1 = @parameter3)
)
С этими результатами я заполняю вторую переменную таблицы:
INSERT INTO @SecondQuery
SELECT u1.*, u2.*
FROM u1
INNER JOIN u2 ON u2.idU1 = u1.idU1
WHERE u1.NONindexedField in (SELECT someField FROM @FirstQuery)
Поскольку в среде QA это было довольно медленно, я следил за планами выполнения. Сначала я взглянул на примерный план. Он увидел, что SecondQuery занимал очень много времени, и я понял, что u1.NONindexedField не имел индекса и занимал приблизительно 97% от общей стоимости.
Но потом я взглянул на фактический план, и там говорилось, что FirstQuery взял 100% от общей стоимости. Я проверил оценочные строки, рассчитанные по предполагаемому плану, и во многих местах он оценил очень мало строк, где фактический план показывал около ста тысяч (100К). Я думал, что это потому, что поле, в котором отсутствовал индекс, было в таблице с небольшим количеством строк (17 КБ), но я все равно создал индекс. К моему удивлению, время запроса было сокращено с 500 до 15 секунд.
Итак, мой вопрос ... почему такая разница в планах выполнения, и как получился фактический план? Я знаю, что «Предполагаемый план» на самом деле не означает «оценку плана», а скорее «план с расчетным количеством строк», но это не объясняет разницу, и определенно не объясняет, почему фактический план сказал мне, что все цена была за запрос, который не нужно оптимизировать ...
Кстати, я сравнил относительное время, и второй запрос действительно занимает около 97% от общего времени выполнения.
Спасибо за чтение!