Вызывает ли обнуление столбцов в ISNULL сканирование таблицы?

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

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

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

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

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

1 ответ

Решение

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

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

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

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

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

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

Возможно, что они имеют в виду, еслиANSI_NULLS выключен, но пример, который они дают в документации WHERE ISNULL([c2],0) > 2; против 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 

Другие вопросы по тегам