5

我们在 SQL Server 2008 (SP1) - 10.0.2531.0 (X64) - Win2008 SP2 (X64) 上遇到了一个奇怪的情况。

这是一个繁重的查询:

select t1.id, t2.id 
from t1, t2
where 
     t1.id = t2.ext_id
     and isnull(t1.vchCol1, 'Null') = isnull(t2.vchCol1, 'Null')
     and isnull(t1.vchCol2, 'Null') = isnull(t2.vchCol2, 'Null')
     .... and about 10 more comparisons with Isnull

UPD:比较的所有列(ID 除外)为varchar(~30...200)
T1 为~1.3 亿行,T2 为~300k 行。

这些查询在相当大的开发服务器上运行约 5 小时- 这很慢,但我们能做什么?

虽然我们研究了可能的优化方式——我们发现,在上面的查询中将“isnull”更改为“coalesce”可以带来双倍的性能提升——并且查询现在运行约 2 小时

UPD:当我们删除所有ISNULL检查并使用t1.vchCol1 = t2.vchCol1时,查询会在 40 分钟后完成

问题是:这是已知的行为,我们应该避免在任何地方使用IsNull吗?

4

4 回答 4

10

我想知道您是否会通过明确拆分案例来看到改进:

...
AND ((t1.vchCol1 = t2.vchCol1) OR (t1.vchCol1 IS NULL AND t2.vchCol1 IS NULL))
AND ((t1.vchCol2 = t2.vchCol2) OR (t1.vchCol2 IS NULL AND t2.vchCol2 IS NULL))
...
于 2011-05-27T13:11:17.647 回答
3

你会发现大多数关于这个主题的文章似乎都与此相矛盾。ISNULL(略)快于COALESCE.

ISNULL和之间的区别COALESCE

COALESCE基本上翻译为CASE 表达式,ISNULL是在数据库引擎中实现的内置。
...
这将产生性能差异,并且查询COALESCE 通常会在这里变得更糟。

ISNULL对比COALESCE

我在几台不同的服务器上多次运行了这些测试,并且ISNULL 似乎始终表现COALESCE出平均 10% 或 12% 的出色表现。但这就是 6 秒和 5.3 秒之间的差异(在我的服务器上每次测试的近似平均运行时间),在一百万次执行过程中。几乎不值得牺牲功能和标准合规性,至少在我使用这些功能的场景中。

COALESCE对比ISNULL对比IS NULL OR

表现最好的是IS NULL ORcase,而这三个之间的差异很小。

于 2011-05-27T13:04:11.760 回答
2

您可能需要考虑向每个包含校验和值的表添加一个计算列。然后,在 ID 列和校验和值上创建索引,最后在连接中使用校验和值。像这样的东西:

Alter Table T1 Add CheckSumId As CHECKSUM(vchCol1, vchCol2, vchCol3)
Alter Table T2 Add CheckSumId As CHECKSUM(vchCol1, vchCol2, vchCol3)

Create NonClustered index idx_T1_Checksum On T1(id, CheckSumId)
Create NonClustered index idx_T2_Checksum On T2(ext_id, CheckSumId)

然后您的查询将变为...

select t1.id, t2.id 
from t1 Inner Join t2
       On t1.id = t2.ext_id
       And T1.CheckSumId = T2.CheckSumId
where  isnull(t1.vchCol1, 'Null') = isnull(t2.vchCol1, 'Null')
     and isnull(t1.vchCol2, 'Null') = isnull(t2.vchCol2, 'Null')

当然,这会使用额外的索引空间,但它只是 2 个整数,应该非常有效。每次插入、更新和删除也会有性能损失,因为需要维护另一个索引。但是,我怀疑这会对性能产生很大影响。

于 2011-05-27T14:51:23.830 回答
1

我意识到这是一年后,但是...

对于这种逐列比较,您可以考虑使用 EXCEPT。此外,EXCEPT 将 NULL 视为另一个值,而不是“它可能是任何东西!”,我喜欢这样称呼它。

“当您比较行以确定不同的值时,两个 NULL 值被认为是相等的。” --来自http://msdn.microsoft.com/en-us/library/ms188055.aspx

于 2012-01-26T23:45:47.470 回答