2010-11-04 1 views
0

У меня есть следующие два SQL заявления«IF..ElseIf..Else» или «Где пункт» для поводырей хранимых процедур приводит к

Первый один:

IF(@User_Id IS NULL) 
BEGIN 
     SELECT * 
     FROM [UserTable] 
END 
ELSE   
BEGIN     
     SELECT * 
    FROM [UserTable] AS u 
    WHERE u.[Id] = @User_Id     
END 

Второй один:

SELECT * 
FROM [UserTable] AS u 
WHERE (@User_Id IS NULL OR u.[Id] = @User_Id) 

Оба этих запроса будут завернуты в собственную хранимую процедуру. Я подозреваю, что оператор IF вызывает много перекомпиляции SQL. Я столкнулся либо с разделением каждой части оператора IF на свою собственную хранимую процедуру, либо с заменой всей инструкции IF предложением WHERE (показано выше во втором заявлении SQL)

Мой вопрос: в чем разница между два утверждения с точки зрения производительности и как SQL обрабатывает каждое утверждение?

Спасибо.

+1

Если вы используете SQL Server 2005+, почему бы не посмотреть на план выполнения, чтобы узнать, в чем разница? –

+0

Кроме того, вам не нужно повторять проверку, если @User_Id НЕ НУЛЛ в вашем заявлении ELSE, поскольку вы знаете, что это не NULL. –

+0

Ardman Я согласен, что «else if» может быть «else» :) – MikeStichling

ответ

0

Оба решения будут генерировать идентичное количество компиляций.

Первое решение оптимизатора запросов может придумать лучший план для каждого из двух разных запросов. Первый запрос (в ветви NULL IF) не так много, что можно оптимизировать, но второй (в ветке NOT NULL идентификатора) можно оптимизировать, если существует индекс в столбце Id.

Но второе решение - это катастрофа для оптимизации. Независимо от значения параметра @User_Id, оптимизатор должен разработать план, который работает для любого значения. Таким образом, независимо от значения @User_Id, план будет всегда использовать субоптимальное сканирование таблицы. Существует просто нет пути вокруг этой проблемы, и это не параметр нюхать, как некоторые могут подумать. Это просто правильность плана, даже если значение при создании плана не равно NULL, план должен работать, даже если параметр равен NULL, поэтому он не может использовать индекс на Id.

Всегда, всегда, всегда используйте первую форму с явным IF.

+0

Спасибо, я немного смущен, но как SQL определяет, нужно ли перекомпилировать Хранимую процедуру. Одним из критериев является изменение статистики. Две разные ветви в IF Statement, возвращают очень разные статистические данные, основанные на значении параметра. Не приведет ли это к тому, чтобы хранимая процедура была отмечена для перекомпиляции? – MikeStichling

+0

Статистика - это свойство объекта (таблицы), а не запроса. Таким образом, два запроса возвратят разные * результаты *, но план будет скомпилирован на основе той же статистики (статистика «UserTable»). Если ваши запросы на самом деле похожи на один грех на ваш пост, то вам не нужно беспокоиться о перекомпиляции, поскольку оба запроса - это то, что si называется «тривиальными запросами», которые имеют очень низкую стоимость компиляции (т. Е. Планы «очевидны») , Даже если повторная компиляция будет иметь место, чаще всего плохой план (например, вариант 2 будет создавать) является более разрушительным, чем перекомпиляция. –

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