Гейл Шоу написал несколько замечательных статей на эту тему: Catch-all Queries и Пересмотр Catch-all Queries .
Сводка этого, однако, такова, что вы находитесь в 2008 году, а затем - параметризованные динамические операторы. Если вы работаете на SQL Server 2012+, тогда введите WHERE Column = @Variable OR @Variable IS NULL
и добавьте OPTION (RECOMPILE)
в конец.
Если, однако, у вас есть дорогостоящий запрос с точки зрения генерации плана запроса, то вы можете по-прежнему использовать динамический SQL. Затем каждое из утверждений будет иметь свой собственный кэшированный план, если они вызываются достаточно часто.
Что бы ни случилось, не идите с status = ISNULL(NULLIF(@user-selected-status-id, -1), status)
. Это предложение не является SARGable и будет иметь худшую производительность из всех.
Итак, метод 2012+ (для плана запроса не высокой сложности с точки зрения генерации) будет:
SELECT {Columns}
FROM YourTable YT
WHERE (YT.Column = @Variable
OR @Variable IS NULL)
OPTION (RECOMPILE);
OPTION (RECOMPILE)
важен, так как он заставляет механизм данных заново создавать план запроса (и оценки) при каждом запуске запроса. Если у вас есть запрос, где @Variable
имеет значение, то число строк, которые будут возвращены, будет оцениваться как «низкое» (соответственно). С другой стороны, для запроса, где значение @Variable
равно NULL
, это означает, что каждая строка будет возвращена (в этом простом запросе); или «большое» количество строк. Планы кэширования в SQL Server. Это означает, что план с небольшим числом не подходит для большого числа. Плохие оценки могут (и могут) означать низкую производительность, поскольку в базе данных tempdb могут возникать проблемы с переполнением оперативной памяти, а время ресурсов не соответствует ожидаемому. Принуждение механизма данных к воссозданию плана означает, что эти оценки будут воссозданы для каждого прогона (что обойдется дорого), но они будут намного лучше для выполняемого запроса; при условии, что ваша статистика тоже актуальна.
Если, однако, вы используете SQL Server 2008, у вас нет доступа к OPTION (RECOMPILE)
, поэтому вам нужно идти по динамическому маршруту:
DECLARE @SQL nvarchar(MAX);
SET @SQL = N'SELECT {Columns}' + NCHAR(13) + NCHAR(10) +
N'FROM YourTable' + NCHAR(13) + NCHAR(10) +
CASE WHEN @Variable IS NOT NULL THEN N'WHERE YT.Column = @Variable' ELSE '' END + N';';
EXEC sp_executesql @SQL, N'@Variable {DataType}', @Variable = @Variable;