将可为空的列包装在 ISNULL 中是否会导致表扫描?

发布于 2024-12-05 11:03:31 字数 481 浏览 4 评论 0原文

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

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

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

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

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

Code analysis rule SR0007 for Visual Studio 2010 database projects states that:

You should explicitly indicate how to handle NULL values in comparison expressions by wrapping each column that can contain a NULL value in an ISNULL function.

However code analysis rule SR0006 is violated when:

As part of a comparison, an expression contains a column reference ... Your code could cause a table scan if it compares an expression that contains a column reference.

Does this also apply to ISNULL, or does ISNULL never result in a table scan?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

以可爱出名 2024-12-12 11:03:31

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

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

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

它声称其理由是

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

虽然表达式本身的计算结果为 unknown,但一旦您了解任何 =<>>< 等与 NULL 的比较评估为 Unknown 并且 WHERE 子句仅返回表达式计算结果为的行

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

在此处输入图像描述

Yes it causes table scans. (though seems to get optimised out if the column isn't actually nullable)

The SR0007 rule is extremely poor blanket advice as it renders the predicate unsargable and means any indexes on the column will be useless. Even if there is no index on the column it might still make cardinality estimates inaccurate affecting other parts of the plan.

The categorization of it in the Microsoft.Performance category is quite amusing as it seems to have been written by someone with no understanding of query performance.

It claims the rationale is

If your code compares two NULL values or a NULL value with any other
value, your code will return an unknown result.

Whilst the expression itself does evaluate to unknown your code returns a completely deterministic result once you understand that any =, <>, >, < etc comparison with NULL evaluate as Unknown and that the WHERE clause only returns rows where the expression evaluates to true.

It is possible that they mean if ANSI_NULLS is off but the example they give in the documentation of WHERE ISNULL([c2],0) > 2; vs WHERE [c2] > 2; would not be affected by this setting anyway. This setting

affects a comparison only if one of the operands of the comparison is
either a variable that is NULL or a literal NULL.

Execution plans showing scans vs seek or below

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文