3

我正在查看我继承的一些代码,我发现了这样一行:

And isnull(IH.CustomerItemNumber, '') <> ''

我的一位前辈似乎在大量的 where 子句或 join 子句中使用了哪一个。在我看来,这是对函数的不必要调用,因此会消耗性能,因为 NULL 永远不会等于空字符串 '',对吧?

具体来说,我将其从特定查询中的连接子句中取出,性能显着提高(从 46-49 秒到 1-3 秒)。

将其替换为AND IH.CustomerItemNumber <> ''

我的评估在这里正确吗?这是多余且缓慢的,可以删除吗?这段代码在什么情况下可能有用?

编辑:那么,NULL 可以等于空字符串吗?

4

4 回答 4

5

这在语义上与以下内容相同:

And IH.CustomerItemNumber <> '' And IH.CustomerItemNumber Is Not Null

因此,它正在检查该列是否既不是空的,也不是空字符串。可能很重要。

更新

在这种情况下,因为我们正在寻找字符串文字(空字符串)的不相等性,所以您至少有三个语义正确的选项:

  • And IH.CustomerItemNumber <> ''
  • And IH.CustomerItemNumber <> '' And IH.CustomerItemNumber Is Not Null
  • And isnull(IH.CustomerItemNumber, '') <> ''

第一个将返回与其他两个相同的结果集,因为无论ansi_nulls设置<> ''如何,都不会匹配空值。

在开发系统的快速测试中,第一个和第二个都使用了索引查找。在几个非常简化的测试之一中,第一个比第二个稍微好一点。

第三个,因为它添加了一个函数调用,可能不像其他的那样使用索引,所以这可能是最糟糕的选择。也就是说,在快速测试中,isnull 能够使用索引扫描。进一步添加Is Not Null到第三个选项实际上加快了它的速度并将其移至索引搜索。去图(GO!GO!查询优化器!)。

与@Gordon 一样,我大多数时候也会选择第二个选项,因为它可以更好地向其他开发人员(或我自己)说明我的意图,并且如果我们要检查另一个可能为空的列是否相等(想想潜在的 ansi_nulls 关闭)。

为了完整起见:

  • And nullif(IH.CustomerItemNumber, '') is not null
  • And case when IH.CustomerItemNumber = '' then null else IH.CustomerItemNumber end is not null
  • And case IH.CustomerItemNumber when '' then null else IH.CustomerItemNumber end is not null

在 SQL Server 中都以完全相同的方式解释(据我所知),并且执行与上面的第三个选项相同。

于 2012-10-25T18:22:15.790 回答
4

代码存在的原因可能是因为应用程序的历史。也许在某个时间点,字段中允许使用 NULL。然后,这些被替换为空字符串。

代码效率低的原因是因为join的优化。 ISNULL()其 ANSI 标准等效COALESCE()项通常会为查询处理增加可忽略不计的开销。(似乎在某些版本的 SQl Server 中,COALESCE()对第一个参数求值两次,如果它是子查询,这是一个问题。)

我的猜测是该字段上有一个索引。当字段单独使用时,SQL Server 知道将索引用于连接。包含在函数调用中时使用索引不够聪明。降低查询速度的是连接优化,而不是函数调用的开销。

就个人而言,如果性能相同,我更喜欢带有显式 NULL 检查的表单:

IH.CustomerItemNumber <> '' and IH.CustomerItemNumber is not null

明确 NULL 处理只能帮助您在将来维护代码。

于 2012-10-25T18:32:51.903 回答
1

您可以用于 NULL 检查:

And (IH.CustomerItemNumber IS NOT NULL) AND (IH.CustomerItemNumber <> '')

顺便说一句, ISNULL ( check_expression , replacement_value ) - 用指定的替换值替换 NULL。

在您的情况下,如果 IH.CustomerItemNumber 的值为 null 那么它将被替换为空值,然后将与空字符串进行比较。

于 2012-10-25T18:22:04.510 回答
0

因为NULL永远不会等于空字符串'',对吧?

NULL 也永远不会不等于空字符串......它既是一次又不是同时。它传达了一种您不确定的状态。

于 2012-10-25T18:40:07.190 回答