выберите 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: для выбора 19 лучших:

для выбора 18 лучших: для выбора 18 лучших:

еще один сбивающий с толку факт заключается в том, что для запроса select top 19 иногда используется индексированное представление, а иногда нет.


person objectbox    schedule 17.11.2011    source источник
comment
Является ли индексированное представление одной из таблиц, упомянутых в предложении FROM? Если да, то меняет ли что-нибудь добавление подсказки WITH (NOEXPAND)?   -  person Damien_The_Unbeliever    schedule 18.11.2011
comment
Представление напрямую не упоминается в запросе, только базовые таблицы. Все работает нормально для второго запроса, но не для первого. На самом деле, я открываю окно запроса SSMS, вставляю второй запрос — он использует индексированное представление, затем я заменяю первые 30 на первые 10 в этом запросе, и план выполнения меняется — индексированное представление вообще не используется!   -  person objectbox    schedule 18.11.2011
comment
Вы вводили DBCC FREEPROCCACHE; DBCC FREESYSTEMCACHE('ALL') между запросами, чтобы гарантировать честный тест?   -  person MicSim    schedule 18.11.2011
comment
Просто мысль левого поля, но пробовали ли вы использовать переменную для оператора top (n)? например выберите верх (@toprows) из ...   -  person AnthonyJ    schedule 19.11.2011
comment
to @MicSim - я попробовал DBCC FREEPROCCACHE; DBCC FREESYSTEMCACHE('ALL') — ничего не меняется — один и тот же план выполнения для обоих случаев.   -  person objectbox    schedule 19.11.2011
comment
для @AnthonyJ - он отлично работает с переменными. Но я не контролирую запросы. Спасибо за предложение, однако   -  person objectbox    schedule 19.11.2011
comment
Вы можете заставить его использовать определенный индекс, добавив подсказку индекса или таблицы в SQL. Что касается того, ПОЧЕМУ это происходит в первую очередь ... планы выполнения помогут. В противном случае все, что я могу думать, это то, что в одном случае он получает 30 лучших записей из статьи 1. в другом случае сначала получаются результаты объединения, а затем получаются 10 лучших записей; потому что база данных видит прирост производительности... была ли обновлена ​​​​статистика по таблицам? много ли удалений/вставок в таблицы? Размеры таблиц позволяют увеличивать их или они должны корректироваться при каждой вставке/обновлении?   -  person xQbert    schedule 21.11.2011
comment
Я это уже писал - видел планы выполнения, и они, конечно, различаются. Это очевидно. Интересно, почему sql выдает такой неэффективный план для первого запроса. Что касается подсказок - я не могу их использовать - я не контролирую запросы. В любом случае спасибо за предложения!   -  person objectbox    schedule 21.11.2011
comment
Можете ли вы опубликовать планы выполнения? Это очень помогло бы нам в диагностике этого.   -  person mwigdahl    schedule 21.11.2011
comment
Я не уверен, что это поможет, но я выложил диаграммы плана выполнения.   -  person objectbox    schedule 22.11.2011


Ответы (1)


Единственное, о чем я могу думать, это, возможно, оптимизатор в первом запросе, который пришел к выводу, что определяющие критерии недостаточно избирательны для использования «лучшего» плана выполнения.

Если вы все еще исследуете это, посмотрите, выдает ли TOP 60, 90, 100, ... второй план выполнения и работает ли он хорошо. Вы также можете повозиться с ним, чтобы увидеть пороговое значение для оптимизатора, чтобы выбрать второй план в этом случае.

Также попробуйте запросы без инструкции order by, чтобы увидеть, влияет ли это на выбор плана запроса (проверьте индекс в этом поле и т. д.).

Кроме того, вы сказали, что не можете использовать подсказки индекса, поэтому, возможно, перепишите, где вы выбираете верхнюю часть X из своей таблицы статей (N1) с кучей операторов exists в вашем предложении where, что обеспечит лучшую производительность для вас.

person Chris Townsend    schedule 21.11.2011
comment
Я не могу изменить запрос. Он производится ORM-Xpo. Я уже экспериментировал с разными значениями в верхней части - для значений, превышающих 25, всегда выбирается индексированное представление, и план выполнения хорош. для значений меньше 17 он всегда не использует индексированное представление. Спасибо за предложения - person objectbox; 21.11.2011
comment
и кроме того, что производительность запросов не является большой проблемой - есть много других способов решить эту проблему. Меня больше интересует ответ на вопрос ПОЧЕМУ? - person objectbox; 21.11.2011