13

Visual Studio 2010 数据库项目的代码分析规则SR0007指出:

您应该通过在 ISNULL 函数中包装每个可以包含 NULL 值的列来明确指示如何处理比较表达式中的 NULL 值。

但是,在以下情况下违反了代码分析规则SR0006

作为比较的一部分,表达式包含列引用...如果您的代码比较包含列引用的表达式,您的代码可能会导致表扫描。

这是否也适用于 ISNULL,或者 ISNULL 永远不会导致表扫描?

4

1 回答 1

20

是的,它会导致表扫描。(尽管如果该列实际上不可为空,似乎会得到优化)

SR0007 规则是极差的一揽子建议,因为它使谓词不可分割,并且意味着列上的任何索引都将无用。即使列上没有索引,它仍然可能使基数估计不准确,从而影响计划的其他部分。

它在Microsoft.Performance类别中的分类非常有趣,因为它似乎是由不了解查询性能的人编写的。

它声称理由是

如果您的代码将两个 NULL 值或一个 NULL 值与任何其他值进行比较,您的代码将返回未知结果。

虽然表达式本身确实会对unknown您的代码进行评估,但一旦您了解任何=, <>,等与评估 as的比较,并且该子句仅返回表达式评估为的行,>就会返回完全确定的结果。<NULLUnknownWHEREtrue

他们的意思可能是 ifANSI_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 

在此处输入图像描述

于 2011-09-19T13:35:57.677 回答