Я опубликовал это как комментарий, но понял, что это, вероятно, ответ.
Писать предикаты как WHERE @Param IS NULL OR Column = @Param
нехорошо, потому что оптимизатор обычно считает, что это не sargable.
Попробуйте этот эксперимент: возьмите наиболее заполненную таблицу и попробуйте запросить просто для поля первичного ключа, которым должен быть ваш кластеризованный индекс:
DECLARE @PrimaryKey int
SET @PrimaryKey = 1
SELECT CoveredColumn
FROM Table
WHERE @PrimaryKey IS NULL
OR PrimaryKeyColumn = @PrimaryKey
SELECT CoveredColumn
FROM Table
WHERE PrimaryKeyColumn >= ISNULL(@PrimaryKey, 0)
AND PrimaryKeyColumn <= ISNULL(@PrimaryKey, 2147483647)
Оба эти оператора SELECT
будут давать идентичные результаты, предполагая, что столбец PK является неотрицательным int
. Но для этого выберите план выполнения, и вы увидите огромную разницу в стоимости. Первый SELECT
выполняет полное сканирование индекса и обычно занимает около 90% стоимости запроса.
Если вы хотите иметь необязательные условия поиска в SQL и не можете использовать динамический SQL, лучше для производительности, если вместо этого вы можете превратить его в запрос диапазона вместо ISNULL
. Даже если диапазон равен огромный (буквально половина диапазона int
здесь), оптимизатор все равно выяснит это, если используется необязательный параметр .