我知道这些函数的区别,但我的问题是在检查单个空值时,使用 ISNULL 是否比使用 COALESCE 更快?
例如:
COALESCE(SELECT TOP 1 SomeValue FROM SomeTable, 0)
对比
ISNULL(SELECT TOP 1 SomeValue FROM SomeTable, 0)
我知道这些函数的区别,但我的问题是在检查单个空值时,使用 ISNULL 是否比使用 COALESCE 更快?
例如:
COALESCE(SELECT TOP 1 SomeValue FROM SomeTable, 0)
对比
ISNULL(SELECT TOP 1 SomeValue FROM SomeTable, 0)
看了一下这个问题,因为看到有很多不同的比较关于它们之间性能的文章。我认为Adam Machanic在他的博客文章中对这个问题所做的性能基准测试最准确,底线是:
... 而ISNULL似乎比COALESCE表现得更出色,在平均值上高出10或12%
然而,我与他接下来所说的观点相同 - 差异是相当微不足道的 - 例如,在他的测试中,一百万次执行的平均差距只有0.7秒。值得吗?我建议可能有更大的优化空间。但是请阅读这篇文章,这很有意思。
ISNULL
会更快,因为它本身的函数/代码实现较少,使其比COALESCE
更快。
ISNULL
而不是COALESCE
的原因是ISNULL
往往会产生比COALESCE
更高效的查询计划。
就其价值而言,你有一个非常具体的用例,因此我在脑海中想到一个表格的第一个in值上使用了你实际问题的样例,并为其他变量控制了脚本。我假设someval是一个整数,因为你使用了0。我的建议是,你选择你特定的someval/sometable情况,并自己进行测试。
declare @val int = 0;
declare @time1 Datetime2 = getdate();
declare @time2 Datetime2 = getdate();
Select @time1 = GETDATE();
while @MyCounter < 1000000
Begin
Select @val = ISNULL((SELECT TOP 1 LocationID FROM location), 0)
Select @MyCounter +=1;
END
Select @time2 = GETDATE();
Print datediff(millisecond,@time1,@time2);
Select @MyCounter = 0;
Select @time1 = GETDATE();
while @MyCounter < 1000000
Begin
Select @val = COALESCE((SELECT TOP 1 LocationID FROM Location), 0)
Select @MyCounter +=1;
END
Select @time2 = GETDATE();
Print datediff(millisecond,@time1,@time2);
结果相当惊人,isnull的计算时间为11270,而coalesce则需18930。将循环顺序颠倒再测试一次后,coalesce的计算时间为18260,isnull则只需10810。对于你的具体情况而言,我认为isnull明显更快。
这并不代表在其他情况下isnull就更好。使用简单值、nvarchars或位(bit)而非int,或者列不是主键,或将isnull嵌套与向coalesce添加参数进行比较等等都可能改变计算结果。
这仅回答了所提出的问题。
我刚刚在自己的数据库上进行了测试。大约有70万行数据。
SELECT COUNT(*) FROM table WHERE COALESCE(field_1,field_2,field_3,field_4) IS NOT NULL
在56秒内获得12106
的结果。
SELECT COUNT(*) FROM table WHERE field_1 IS NOT NULL OR field_2 IS NOT NULL OR field_3 IS NOT NULL OR field_4 IS NOT NULL
在0.00秒内获得12106
的结果。
WHERE !ISNULL(field_1)...
重新运行测试。但是我们难道不能相当确定调用 ISNULL()
函数的速度甚至比使用 IS NOT NULL
还要慢吗? - Buttle Butkus