(Вопрос перенесен с ТАК)
У меня таблица (фиктивные данные) с кластерным индексом содержит 2 столбца:
Теперь я запускаю эти два запроса:
declare
@productid int =1 ,
@priceid int = 1
SELECT productid,
t.priceID
FROM Transactions AS t
WHERE (productID = @productid OR @productid IS NULL)
AND (priceid = @priceid OR @priceid IS NULL)
SELECT productid,
t.priceID
FROM Transactions AS t
WHERE (productID = @productid)
AND (priceid = @priceid)
Фактический план выполнения для обоих запросов:
Как видите, первый использует SCAN, а второй использует SEEK.
Однако - добавив OPTION (RECOMPILE)к первому запросу, составил план выполнения и для использования SEEK:
Друзья в чате DBA сказали мне, что:
В вашем запросе @ productid = 1, что означает, что (productID = @ productID OR @productID IS NULL) можно упростить до (productID = @ productID). Первый требует сканирования для работы с любым значением @productID, второй может использовать поиск. Поэтому, когда вы используете RECOMPILE, SQL Server посмотрит, какое значение вы на самом деле имеете в @productID, и составит лучший план для него. При ненулевом значении в @productID поиск является лучшим. Если значение @productID неизвестно, план должен соответствовать любому возможному значению в @productID, что потребует сканирования. Имейте в виду: OPTION (RECOMPILE) будет принудительно перекомпилировать план при каждом его запуске, что будет добавлять несколько миллисекунд к каждому выполнению. Хотя это проблема, только если запрос выполняется очень часто.
Также :
Если @productID равен нулю, какое значение вы бы искали? Ответ: искать нечего. Все значения соответствуют требованиям.
Я понимаю, что OPTION (RECOMPILE)вынуждает SQL Server видеть, какие фактические значения имеют параметры, и посмотреть, может ли он с ним ПОИСКАТЬ.
Но теперь я теряю преимущество предварительной компиляции.
Вопрос
ИМХО - СКАНИРОВАНИЕ произойдет, только если параметр равен нулю.
Это нормально - пусть SQL SERVER создаст план выполнения для SCAN.
НО, если SQL Server видит, что я выполняю этот запрос много раз со значениями: 1,1почему тогда он не создает ДРУГОЙ план выполнения и не использует для этого SEEK?
AFAIK - SQL создает план выполнения для наиболее популярных запросов .
Почему SQL SERVER не сохраняет план выполнения для:
@productid int =1 , @priceid int = 1
(Я запускаю его много раз с этими значениями)
- Можно ли заставить SQL сохранить этот план выполнения (который использует SEEK) - для будущего вызова?


