Выберите топ-10... и выберите верхнюю 30, следуя за другим планом выполнения
Во время оптимизации запроса я обнаружил странное поведение SQL-сервера (Sql Server 2008 R2 Enterprise). Я создал несколько индексов на таблицах, а также некоторые индексированные представления. У меня есть два запроса, например:
select top 10 N0."Oid",N1."ObjectType",N1."OptimisticLockField" from ((("dbo"."Issue" N0
inner join "dbo"."Article" N1 on (N0."Oid" = N1."Oid"))
inner join "dbo"."ProductLink" N2 on (N1."ProductLink" = N2."Oid"))
inner join "dbo"."Technology" N3 on (N2."Technology" = N3."Oid"))
where (N1."GCRecord" is null and (N0."IsPrivate" = 0) and ((N0."HasMarkedAnswers" = 0) or N0."HasMarkedAnswers" is null) and (N3."Name" = N'Discussions'))
order by N1."ModifiedOn" desc
и
select top 30 N0."Oid",N1."ObjectType",N1."OptimisticLockField" from ((("dbo"."Issue" N0
inner join "dbo"."Article" N1 on (N0."Oid" = N1."Oid"))
inner join "dbo"."ProductLink" N2 on (N1."ProductLink" = N2."Oid"))
inner join "dbo"."Technology" N3 on (N2."Technology" = N3."Oid"))
where (N1."GCRecord" is null and (N0."IsPrivate" = 0) and ((N0."HasMarkedAnswers" = 0) or N0."HasMarkedAnswers" is null) and (N3."Name" = N'Discussions'))
order by N1."ModifiedOn" desc
оба запроса одинаковы, кроме первого запуска с выберите топ 10, а второй с выберите верхнюю 30. Оба запроса возвращают один и тот же набор результатов - 6 строк. Но второй запрос в 5 раз быстрее, чем первый! Я рассмотрел фактические планы выполнения для обоих запросов, и, разумеется, они отличаются. Второй запрос использует индексированное представление и отлично работает, и первый запрос отрицает его использование, вместо этого использует индексы на таблицах. Повторяю - оба запроса одинаковы, в одной и той же таблице, на одном сервере, они отличаются только числом в "верхней" части.
Я попытался заставить оптимизатор использовать индексированный вид в первом запросе, обновив статистику, уничтожив индексы, которые он использовал, и так далее. Независимо от того, как я пытаюсь выполнить фактическое выполнение, не используйте индексированное представление для первого запроса и всегда используйте его для второго.
Меня действительно интересуют причины, вызывающие такое поведение. Любые предложения?
Обновление. Я не уверен, что он может помочь без указания соответствующих индексов и представлений, но это фактические диаграммы плана выполнения:
для выбора верхней 19:
![for select top 19:]()
для выбора верхней части 18:
![for select top 18:]()
другой запутанный факт заключается в том, что для запроса select top 19 иногда используется индексированное представление, иногда не
Ответы
Ответ 1
Единственное, о чем я могу думать, - возможно, оптимизатор в первом запросе пришел к выводу, что определяющие критерии не являются достаточно избирательными, чтобы "лучший" план выполнения был использован.
Если вы все еще изучаете это, смотрите, если TOP 60, 90, 100,... производит второй план выполнения и хорошо работает. Вы также можете поработать с ним, чтобы узнать, какой порог для оптимизатора для выбора второго плана в этом случае.
Также попробуйте запросы без инструкции order by, чтобы узнать, влияет ли это на выбор плана запроса (проверьте индекс в этом поле и т.д.)
Кроме того, вы сказали, что не можете использовать подсказки для индекса, поэтому, возможно, перепишите, где вы выбираете верхний X из своей таблицы статей (N1) с кучей существующих операторов в своем предложении where, который обеспечит лучшую производительность для вас.