多列UPDATE-JOIN与多ISNULL需要很长时间?

Cha*_*adD 7 sql join isnull sql-server-2008

我们在数据库中有一个存储过程,它通过连接30个列上的2个表和where条件来更新表.SQL的一般格式为:

UPDATE Target
SET col1 = Source.col1
INNER JOIN Source 
on 
ISNULL(Target.Col2, '') = ISNULL(Source.Col2, '') and
ISNULL(Target.Col3, '') = ISNULL(Source.Col3, '') and
.
.
.
ISNULL(Target.Col31, '') = ISNULL(Source.Col31, '') and 
Run Code Online (Sandbox Code Playgroud)

这是查询计划.将其保存到您的PC并重新打开,以便更好地扩展.

在此输入图像描述

Source表有65M记录,Target 165M.以前它曾经在很长一段时间内运行.考虑到查询的丑陋和潜在的低效率,我发现这令人惊讶.这个月它运行了1.5个小时,使用了100%的处理器,我们不得不杀死它.

任何建议如何即兴创作以下查询并使其按时运行..?

我们在30-col连接条件中使用的一些列上有单列索引.

我知道ISNULL函数和30列的连接是坚果,这是一个糟糕的设计.不要怪我,我继承了这个经济.

不幸的是,没有时间进行重新设计.有什么建议?

usr*_*usr 5

  1. 请发布估算执行计划的屏幕截图
  2. 我怀疑之前的查询使用了散列连接(它应该),但不知何故,基数估计现在错了,你得到一个循环连接.在查询上打开散列连接提示,看它是否修复了this(INNER HASH JOIN).一旦我们有了确切的计划,我们就可以说更多.
  3. 将等式更改为(A1 = A2 OR (A1 IS NULL AND A2 IS NULL)).SQL Server实际上识别此模式并在内部将其转换为"完全等于没有愚蠢的空语义".即使使用空值,也可以通过这种方式查找索引.

如果这没有用,请务必执行步骤(3)并在col2-col31上创建覆盖索引,包括col1.这将为您提供合并连接,这是本案例中最有效的计划.它真的很快.警告:这会使表的磁盘大小加倍并降低更新速度.