Не знаете, с чего начать с этого - не уверен, что проблема в том, что я обманываю оптимизатор запросов, или если это что-то внутреннее к способу работы индексов, когда задействованы нули.Оптимизация запросов SQL Server: где (Col = @ Col или @ Col = Null)
Одно кодирования конвенции я следовал, чтобы кодировать хранимые процедуры, как, например:
declare procedure SomeProc
@ID int = null
as
select
st.ID,st.Col1,st.Col2
from
SomeTable st
where
(st.ID = @ID or @ID is null) --works, but very slow (relatively)
Не очень полезно в этом простом тесте, конечно, но полезные в других сценариях, когда вы хотите, хранимую процедуру для действовать либо по всей таблице, либо по строкам, удовлетворяющим некоторым критериям. Тем не менее, это довольно медленно при использовании на больших столах ... примерно 3-5x медленнее, чем если бы я заменил, где положение с:
where
st.ID = @ID --3-5x faster than first example
Я еще озадачен тем фактом, что заменяющий нуль с -1 дает мне почти такую же скорость, что и «фиксированный» ИНЕКЕ выше:
declare procedure SomeProc
@ID int = -1
as
select
st.ID,st.Col1,st.Col2
from
SomeTable st
where
(st.ID = @ID or @ID=-1) --much better... but why?
Очевидно, что это нулевая, что делает вещи дурацкие, но почему именно? Ответ на это не ясен, когда я рассматриваю план исполнения. Это то, что я заметил на протяжении многих лет в различных базах данных, таблицах и выпусках SQL Server, поэтому я не думаю, что это причуда моей текущей среды. Я решил проблему, переключив значение параметра по умолчанию от нуля до -1; мой вопрос почему это работает.
Примечания
- SomeTable.ID индексируется
- Это может быть связано с (или может, на самом деле, быть) параметр нюхают вопрос Parameter Sniffing (or Spoofing) in SQL Server За то, что он стоит, я был тестирование почти исключительно с «exec SomeProc» после каждого редактирование/перекомпиляция proc, т. Е. С необязательный параметр опущен.
Спасибо большое за ответ. Я подозреваю, что это было больше всего. Я был довольно не осведомлен о том, насколько дорого или может быть. В конце концов, после вашей реплики, я пошел с SET @ ID = ISNULL (@ ID, -1) в верхней части сохраненного proc для удобства чтения. (Фактическая сохраненная процедура довольно длинная, и я не хочу похоронить «по умолчанию» глубоко внутри. Спасибо еще раз. –