是否使用COALESCE会降低查询性能

时间:2014-04-30 11:20:23

标签: sql-server

我很想知道使用COALESCE会降低查询性能。我在一篇文章中读到它,我们应该避免使用COALESE而不是它,我们应该使用案例。关于COALESE它是否真的存在阻碍查询性能的问题?任何帮助将不胜感激。

由于

7 个答案:

答案 0 :(得分:3)

我无法确定SQL Server。但是,我将在Oracle中提供我的经验,以防万一可能存在相关性。这取决于您使用它的上下文。 例如,考虑一下SQL语句中可能有谓词的情况,如下所示:

SELECT UserId, FirstName, Surname,  DepartmentId
FROM Users
WHERE DepartmentId = COALESCE(pDepartmentId,DepartmentId)

在这种情况下使用COALESCE(至少在Oracle中 - 是的,我意识到这是一个SQL Server问题)会排除在DepartmentId上使用任何索引。

正如我所说,这取决于上下文,虽然这是从Oracle的角度来看,但我怀疑这同样适用于SQL Server。

修改

我刚刚在您使用它的上下文中看到了您的帖子,它与上面的内容完全相同。

你可以在你的情况下尝试的是以下这是我学会避免这个问题的一个巧妙的技巧 - 再次 - 甲骨文,但可以为你工作。

SELECT UserId, FirstName, Surname,  DepartmentId
FROM Users
WHERE pDepartmentId IS NOT NULL AND DepartmentId = pDepartmentId

UNION ALL

SELECT UserId, FirstName, Surname,  DepartmentId
FROM Users
WHERE pDepartmentId IS NULL

很抱歉在SQL Server帖子上进行交互,但如果这对你有所帮助,那么它可能是值得的。

最终修改

正如我在下面评论的那样,CASE声明的确解决了这个问题。因此,不需要过于复杂的UNION黑客攻击(它可以提供与CASE相同的成本)。不幸的是,我仍然需要在Oracle中使用它。 MSSQL案例的另一个胜利(没有双关语!!)

答案 1 :(得分:1)

COALESCE可能会影响您的效果,但不会与CASE进行比较,因为它实际上只是CASE的另一个名称。

在某些情况下,

ISNULL可能会导致更好的性能。但要注意它们之间的其他差异,主要是返回类型。

比较这三个查询的执行计划:

use AdventureWorks2012;
go
select coalesce((select CustomerID from Sales.SalesOrderHeader where SalesOrderId = 10000), 0)
select isnull((select CustomerID from Sales.SalesOrderHeader where SalesOrderId = 10000), 0)
select case 
    when (select CustomerID from Sales.SalesOrderHeader where SalesOrderId = 10000) is null then 0
    else (select CustomerID from Sales.SalesOrderHeader where SalesOrderId = 10000)
end

答案 2 :(得分:1)

以我的经验,对于SQL Server 2016 +,COALESCE是真正的狗性能。尤其是在SQL 2016之后。我们经验的一个示例是我们编写的存储过程,其中包括一个WHERE子句,该子句包含8个COALESCE语句。在大型数据集(约30万行)上,此存储过程运行了将近一分钟。当我们将数字减少为1条COALESCE语句时,同一查询在不到一秒钟的时间内就运行了。那是唯一的变化。

我知道这是轶事,老实说我不能告诉你为什么它开始表现如此差劲,但这就是我们的经验。也许这是数据库配置问题。如果情况相反,如果您可以使用IS NULL进行检查,则可以节省一些麻烦。

答案 3 :(得分:0)

谁说的?

仅供参考:

1)它是ANSI标准(vs isnull)

2)它提供更多的功能,因为它需要超过1个参数。

3)最快的方法是:if @s is null...

4)它真的会伤害你的表现吗?我怀疑。

答案 4 :(得分:0)

与任何函数一样,COALESCE具有它的位置,它是ANSI 92 SQL标准的一部分,这意味着它在RDMBS中广泛实现。如果您只需要对一个值进行测试,则可以使用ISNULL。虽然有些人会抱怨这不符合SQL标准(这是真的),但很多平台都会以某种形式实现它。

封底COALESCE实际上等同于CASE声明,但我不确定ISNULL

有一个非常好的写作和讨论on this MSDN Blog。是的, ARE 有可能会受到性能影响的情况,但它们非常具体,如该博客所详述。

tl; dr - 课程的马匹。如果您需要在系列中找到第一个非null,那么COALESCE适合您,否则ISNULL就足够了。与往常一样,如果您担心性能(并且仅在某些情况下您应该关注COALESCE - 请参阅一个示例的链接)然后与执行计划以及如何解释它们。

答案 5 :(得分:0)

我目前正在审查最常执行的程序,并查看平均持续时间较长的程序。我看到很多情况我们在WHERE子句中使用COALESCE的可选参数,如下所示: WHERE schedule.CustNum = COALESCE(@CustNum,Schedule.CustNum)

这些程序本身运行缓慢。当它们被编译时,COALESCE会抛弃编译器,并最终使用扫描整个表的计划。随着我们变得越来越大随着我们的卷越来越大,这已经成为一个问题,在某些情况下,如果没有使用可选参数,当它几乎立即运行时,我们最终会运行一个耗时超过10秒的过程

答案 6 :(得分:0)

我遇到了一个性能很差的视图,其中一个小堆中的varchar(30)列的2个实例的COALESCE(在SELECT子句中)连接了两次。对无害吗?我从来都不会相信这是问题所在,但是在分解,隔离和索引一个小时之后,我出于绝望而尝试切换到CASE语句。运行时间从1:42降低到0:00。我还是不明白。执行计划表明工作表上的哈希匹配。 SS版本是2017年。