У меня есть запрос, который объединяет несколько таблиц и выполняет его довольно плохо - оценки строк удалены (в 1000 раз) и выбрано объединение Nested Loops, что приводит к нескольким сканированиям таблиц. Форма запроса довольно проста, выглядит примерно так:
SELECT t1.id
FROM t1
INNER JOIN t2 ON t1.id = t2.t1_id
LEFT OUTER JOIN t3 ON t2.id = t3.t2_id
LEFT OUTER JOIN t4 ON t3.t4_id = t4.id
WHERE t4.id = some_GUID
Играя с запросом, я заметил, что когда я намекаю на использование объединения слиянием для одного из объединений, он выполняется во много раз быстрее. Это я могу понять - объединение слиянием - лучший вариант для объединенных данных, но SQL Server просто не оценивает правильность выбора вложенных циклов.
Что я не до конца понимаю, так это то, почему этот намек на объединение меняет все оценки для всех операторов плана? Из прочтения различных статей и книг я предположил, что оценки количества элементов выполняются до того, как составлен план, поэтому использование подсказки не изменило бы оценки, а скорее явно указало бы SQL Server использовать конкретную реализацию физического объединения.
Однако я вижу, что подсказка Merge делает все оценки в значительной степени идеальными. Почему это происходит, и существуют ли какие-либо распространенные методы, позволяющие оптимизатору запросов делать более точную оценку без намеков - учитывая, что статистика, очевидно, учитывает это?
UPD: анонимные планы выполнения можно найти здесь: https://www.dropbox.com/s/hchfuru35qqj89s/merge_join.sqlplan?dl=0 https://www.dropbox.com/s/38sjtv0t7vjjfdp/no_hints_join.sqlplan?dl = 0
Я проверил статистику, используемую обоими запросами с использованием TF 3604, 9292 и 9204, и они идентичны. Однако сканируемые / разыскиваемые индексы отличаются между запросами.
Кроме того, я попытался выполнить запрос с OPTION (FORCE ORDER)
- он работает даже быстрее, чем с помощью объединения слиянием, выбирая HASH MATCH для каждого соединения.