Подтвердить что ты не робот

Стоит ли обнулять столбцы с нулевым значением в ISNULL, сканирование таблицы?

Правило анализа кода SR0007 для проектов базы данных Visual Studio 2010 гласит, что:

Вы должны явно указать, как обрабатывать значения NULL в выражениях сравнения, обертывая каждый столбец, который может содержать значение NULL в функции ISNULL.

Однако правило анализа кода SR0006 нарушается, когда:

Как часть сравнения, выражение содержит ссылку на столбцы... Ваш код может вызвать сканирование таблицы, если он сравнивает выражение, содержащее ссылку на столбец.

Это также относится к ISNULL, или ISNULL никогда не приводит к сканированию таблицы?

4b9b3361

Ответ 1

Да, это вызывает сканирование таблицы. (хотя кажется, что он оптимизирован, если столбец не является нулевым)

Правило SR0007 - крайне плохой совет по офсету, поскольку он предает предикат unsargable и означает, что любые индексы в столбце будут бесполезны. Даже если в столбце нет индекса, он все равно может сделать оценки мощности неточными, влияющими на другие части плана.

Категоризация его в категории Microsoft.Performance довольно забавна, поскольку, похоже, она написана кем-то, не понимая производительности запросов.

Он утверждает, что обоснование

Если ваш код сравнивает два значения NULL или значение NULL с любым другим значение, ваш код вернет неизвестный результат.

В то время как само выражение оценивает unknown, ваш код возвращает полностью детерминированный результат, как только вы поймете, что сравнение =, <>, >, < и т.д. NULL оценивается как unknown и что предложение WHERE возвращает только строки, в которых выражение оценивается как true.

Возможно, они означают, что если ANSI_NULLS выключен, но пример, который они приводят в документации WHERE ISNULL([c2],0) > 2; vs WHERE [c2] > 2;, не будет затронут эта настройка в любом случае. Этот параметр

влияет на сравнение только в том случае, если один из операндов сравнения либо переменная, которая является NULL, либо буквальный NULL.

Планы выполнения, показывающие сканирование против поиска или ниже

CREATE TABLE #foo
  (
     x INT NULL UNIQUE
  )

INSERT INTO #foo
SELECT ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM   sys.all_columns

SELECT *
FROM   #foo
WHERE  ISNULL(x, 10) = 10

SELECT *
FROM   #foo
WHERE  x = 10

SELECT *
FROM   #foo
WHERE  x = 10
        OR x IS NULL 

enter image description here