Оптимизация T-SQL ISNULL () - PullRequest
       24

Оптимизация T-SQL ISNULL ()

6 голосов
/ 18 сентября 2009

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

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

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

Ответы [ 7 ]

7 голосов
/ 18 сентября 2009

в этом случае у меня будет оператор 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
3 голосов
/ 18 сентября 2009

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

Начиная с SQL 2005, вы можете направлять оптимизатор, используя опцию «OPTIMIZE FOR»: -

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'))
3 голосов
/ 18 сентября 2009
AND @due_date_limit IS NULL OR b.due_date <= @due_date_limit

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

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

есть ли индекс по 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) или фильтрация с использованием <= может потенциально вернуть значительное количество записей, что исключит любую возможность использования индекса и потребует полного сканирования таблицы. Это может быть то, что вы испытываете. </p>

1 голос
/ 18 сентября 2009
COALESCE(@due_date_limit, b.due_date)

может помочь

1 голос
/ 18 сентября 2009

@ 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>
0 голосов
/ 08 июля 2013

Поскольку @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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...