2015-10-08 2 views
1

Во-первых, я прошу прощения, если этот вопрос является общим ... Я не могу найти правильные условия для поиска ...Оптимизация запросов с переменными

У меня есть несколько большая таблица, которая инкрементный ID и вставленное значение datetime. На нем есть пара индексов, включая первичный ключ на ID и некластеризованный индекс по вставленному времени и идентификатору. Так что, когда я пишу запрос вроде следующего, это очень быстро:

select min(ID), max(ID) 
from tbl 
where inserted between '2015-10-07' and '2015-10-08' 

Однако, если я variablize в случаях, когда условия пункта (как показано ниже), это совсем немного медленнее:

declare @sTime datetime, @eTime datetime 
select @sTime = '2015-10-07', @eTime = '2015-10-08' 

select min(ID), max(ID) 
from tbl 
where inserted between @sTime and @eTime 

Когда Я смотрю на два плана запросов, я вижу очевидную проблему. В первом запросе используется один seek для некластеризованного индекса введенного времени и идентификатора. Однако второй запрос вместо этого выполняет 2 scans на первичный ключ (который является только идентификатором).

Итак, мой вопрос заключается в два раза:

  1. Почему SQL Server выполняет эти оптимизации и
  2. как я могу это исправить?
+2

[Параметры] (http://www.sommarskog.se/query-plan-mysteries.html#varparamreplace) результирующий автономный запрос совсем другой, и SQL Server может делать ** более точные оценки с константами вместо переменных **, и, следовательно, прийти к лучшему плану. Вы можете попытаться использовать другой план с помощью [Гиды планов] (http://www.sommarskog.se/query-plan-mysteries.html#planguides) – lad2025

+0

Просто точка в том, что в зависимости от диапазона запросов оптимизатор запросов должен выбирать между index seek vs index scan. – lad2025

+0

@ lad2025, в то время как я не думаю, что ссылка параметров имеет какое-то отношение к моему сценарию (это не хранимая процедура), похоже, что 'option (recompile)' должен работать в MSSQL 2008 и newer ... что, по крайней мере, подразумевает, что существует разумное решение, продвигающееся вперед ... – chezy525

ответ

3

Вы страдаете от неявного OPTION (OPTIMIZE FOR UNKNOWN) с использованием локальных переменных. См. this link для получения дополнительной информации. Оптимизатор не может параметрировать sniff локальные переменные и использует общий план, основанный на средних значениях. При использовании констант он может использовать лучшие статистические данные и оптимизировать с помощью поисковых систем.

Чтобы исправить это, вы можете захотеть создать хранимую процедуру и предоставить параметры вместо переменных. Возможно, вам понадобится добавить подсказку OPTION (RECOMPILE), чтобы получить аналогичные оптимизации, как при использовании констант. В противном случае вы будете подвержены тем, какие параметры были обнюханы во время первого выполнения.

+0

Это выглядит точно так. Простое изменение переменных для ввода параметров хранимой процедуры привело к правильной оптимизации. – chezy525

+0

«общий план, основанный на средних показателях» - каковы эти средние значения? средние из чего? – BornToCode

+0

Средние значения основаны на компоненте плотности_vector статистики на вашей таблице. SQL Server использует это, пытаясь создать план выполнения, который является «достаточно хорошим», имея неполную информацию о параметрах. – CElliott

Смежные вопросы