Необязательные параметры в хранимых процессах - CASE vs. OR - PullRequest
2 голосов
/ 11 сентября 2009

Есть ли разница в производительности между этими методами фильтрации?

Method 1: WHERE (@Col1 IS NULL OR t.column = @Col1) 


Method 2: WHERE 1 = case when @col1 is null then 1 else case when col1 = @col1 then 1 else 0 end end

Ответы [ 3 ]

2 голосов
/ 11 сентября 2009

Если вы знаете, что ваш столбец Col1 не содержит никаких нулевых значений, вы можете сделать это:

WHERE Col1 = COALESCE(@Col1, Col1)

В противном случае ваш оператор CASE должен обычно работать немного лучше, чем OR. Я добавляю акцент на «обычно», потому что когда-либо таблица отличается. Вы должны всегда профиль, чтобы знать наверняка.

К сожалению, обычно самый быстрый способ заключается в использовании динамического sql для исключения условия из запроса, в первую очередь, если параметр имеет значение null. Но, конечно, сохраните это как оптимизацию последней инстанции.

2 голосов
/ 11 сентября 2009

Да. CASE имеет гарантированный порядок исполнения, а OR - нет. Многие программисты полагаются на короткое замыкание ИЛИ и удивляются, узнав, что ориентированный на множество декларативный язык, такой как SQL, не гарантирует короткое замыкание логического оператора.

Сказанное с использованием OR и CASe в предложениях WHERE является плохой практикой. Разделите условие на четкое выражение IF и задайте отдельные запросы для каждой ветви:

IF @col1 IS NOT NULL
  SELECT ... WHERE col1 = @col1;
ELSE
  SELECT ... WHERE <alternatecondition>;

Помещение условия в WHERE обычно побеждает оптимизатор, который не может угадать, каким будет @ col1, и выдает неверный план, включающий полное сканирование.

Обновление

Поскольку мне надоело снова и снова объяснять, что логическое короткое замыкание не гарантируется в SQL, я решил написать об этом целую колонку блога: Короткое замыкание логического оператора SQL Server . Там вы найдете простой пример счетчика, показывающий, что логическое короткое замыкание не только не гарантировано , но и полагаться на него на самом деле может быть очень опасным, поскольку может привести к ошибки времени выполнения .

2 голосов
/ 11 сентября 2009

Почему бы не использовать Coalesce?

Where Col1 = Coalesce(@Col1, Col1)

РЕДАКТИРОВАТЬ: (спасибо комментарию Джоэла ниже). Это работает только в том случае, если col1 не допускает пустых значений или если разрешены пустые значения и вы хотите, чтобы нулевые значения были исключены, когда @ Col1 равно нулю или отсутствует. Поэтому, если он допускает значения NULL и вы хотите, чтобы они включались , когда параметр @ Col1 равен нулю или отсутствует, измените его следующим образом:

 Where Coalesce(@Col1, Col1) Is Null Or Col1 = Coalesce(@Col1, Col1)  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...