Запрос как
select *
from foo
where foo.bar = @p OR @p is null
может или не может вызвать сканирование таблицы. Мой опыт в том, что он не будет: оптимизатор отлично умеет делать индексный поиск по выражению foo.bar = @p
, предполагая подходящий индекс. Кроме того, он отлично способен закоротить объекты, если переменная равна нулю. Вы не будете знать, как выглядит ваш план выполнения, пока вы не попробуете его и не проверите связанную плоскость выполнения. Лучшей техникой является, однако, следующее:
select *
from foo
where foo.bar = coalesce(@p,foo.bar)
, который даст вам такое же поведение.
Если вы используете хранимые процедуры, одна вещь, которая может и укусить вас в tookus что-то вроде этого:
create dbo.spFoo
@p varchar(32)
as
select *
from dbo.foo
where foo.bar = @p or @p = null
return @@rowcount
Прямое использование параметра хранимой процедуры в котором положение будет вызывать план кеширования должен быть основан на значении @p
при его первом выполнении.Это означает, что если первое выполнение вашей хранимой процедуры имеет значение outlier для @p
, вы можете получить план выполнения кэширования, который действительно работает для 95% «нормальных» исполнений и действительно хорош только для случаев с нечеткой ситуацией. Чтобы предотвратить это, вы хотите сделать это:
create dbo.spFoo
@p varchar(32)
as
declare @pMine varchar(32)
set @pMine = @p
select *
from dbo.foo
where foo.bar = @pMine or @pMine = null
return @@rowcount
Это простое задание параметра локальной переменной делает это выражение и поэтому кэшировать план выполнения не связан с начальным значением @p
. Не спрашивайте, как я это знаю.
Далее рекомендация вы получили:
Во многих случаях, OPTION (RECOMPILE) намек может быть быстрым обходным путем. С точки зрения дизайна, вы также можете рассмотреть возможность использования отдельных аргументов If или (не рекомендуется) с помощью динамического оператора SQL.
- hogwash. Option(recompile)
означает, что хранимая процедура перекомпилируется при каждом исполнении. Когда скомпилированная хранимая процедура компилируется, блокировка времени блокируется на зависимом объекте. Кроме того, никто другой не сможет выполнить хранимую процедуру до завершения компиляции. Это, скажем так, отрицательное влияние на параллелизм и производительность. Использование option(recompile)
должно быть крайней мерой.
Пишите чистый SQL и проверяйте свои планы выполнения с использованием производственных данных или как можно ближе к нему: на ваш план выполнения влияет размер и форма/распределение данных.
Я не вижу, чтобы вы использовали подстановочные знаки вообще. –
Единственный шаблон, который я вижу, находится в предложении select. Всегда полезно перечислить (и свести к минимуму) возвращаемые столбцы. О чем говорит ваш обзор? – Malk
термин «подстановочный знак» вводит в заблуждение, он ссылается на используемую технику where where (которую я использовал несколько раз сам) – CodeMonkey1313