我正在查看我继承的一些代码,我发现了这样一行:
And isnull(IH.CustomerItemNumber, '') <> ''
我的一位前辈似乎在大量的 where 子句或 join 子句中使用过。在我看来这是对函数的不必要调用,因此会消耗性能,因为 NULL 永远不会等于空字符串 '',对吧?
具体来说,我在特定查询中将其从连接子句中取出,性能显着提高(从 46-49 秒到 1-3 秒)。
将其替换为 AND IH.CustomerItemNumber <> ''
我的评估是否正确?这是多余且缓慢的,可以删除吗?这段代码在什么情况下可能有用?
编辑:那么,NULL 可以等于空字符串吗?
最佳答案
这在语义上与:
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 一样,我大多数时候也会选择第二个选项,因为它可以更好地向其他开发人员(或我自己)说明我的意图,并且如果我们要检查另一个列的相等性,这将是一个更好的做法,这可能是null(想想潜在的 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 中都以完全相同的方式解释(据我所知),并且执行与上述第三个选项相同。
关于SQL 为什么使用 isnull(field, '' ) <> '' ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13074730/