T-SQL Isnull() оптимизация

У меня есть это предложение о соединении в хранимой процедуре, которую я унаследовал:

WHERE a.is_active = 1
AND b.due_date <= ISNULL(@due_date_limit, b.due_date)

Как бы я переписал это, чтобы удалить ISNULL, поскольку это вызывает серьезные проблемы с производительностью?

7 ответов


в этом случае у меня будет оператор if, проверяющий @due_date_limit

IF (@due_date_limit IS NULL)
BEGIN
    ...
    WHERE   a.is_active = 1 --not required to compare b.due_date <= b.due_date
END
ELSE
BEGIN
    ...
    WHERE   a.is_active = 1
    AND     b.due_date <= @due_date_limit
END

наиболее распространенной причиной низкой производительности с этим типом запроса является то, что оптимизатор не может быть уверен, какое обычно значение @due_date_limit будет для большинства запросов. Часто план, созданный и повторно используемый последующими исполнениями, благоприятствует случаю, когда значение равно null.

начиная с SQL 2005 вы можете направлять оптимизатор, используя опцию" оптимизировать для": -

WHERE a.is_active = 1
AND b.due_date <= ISNULL(@due_date_limit, b.due_date)
OPTION (OPTIMIZE FOR (@due_date_limit = '09/01/2009'))

AND @due_date_limit IS NULL OR b.due_date <= @due_date_limit

но я не уверен, что это будет гораздо быстрее.


есть ли индекс на due_Date? Если не добавить один, а затем проверить производительность. Если уже есть, то измените на два отдельных оператора

  If @due_date_limit is null
    Select [stuff]
    From Table
  Else
    Select [stuff]
    From Table  
    Where b.due_date <= @due_date_limit

но поймите, что не фильтрация (когда @due_date_limit равно null) или фильтрация с помощью


@due_date_limit-это переменная хранимой процедуры, поэтому она может быть учтена из этого запроса вместе:

if (@due_date_limit is NULL) 
   <run query that works when @due_date_limit is NULL>
else 
   <run query that works when @due_date_limit is NOT NULL>

COALESCE(@due_date_limit, b.due_date)

может поможет


С @due_date_limit является переменной хранимой процедуры, вы можете просто проверить его на NULL перед запросом и установите его в значение по умолчанию, если это необходимо, таким образом, устраняя проверку ISNULL в WHERE предложения.

IF (@due_date_limit IS NULL)
BEGIN
    SET @due_date_limit = '09/01/2009';
END

и тогда ваш WHERE предложение будет просто выглядеть так:

WHERE a.is_active = 1
AND b.due_date <= @due_date_limit