加入更新需要太长时间

时间:2016-01-19 15:51:43

标签: sql sql-server tsql

以下查询返回大约80K记录:

这个select只需要大约2秒钟回来:

select fs.fsID
from datFS fs
join datAE t2
on fs.fsID= t2.fsID
join @AllCompletedNotYetDeleted t1
on fs.fsID=t1.fsID
where DateSent < DATEADD(m, -6, GETDATE())

虽然他的update(具有完全相同的联接)正在永远...我必须每次都停止它,所以它还没有结束......

update fs set fs.testrun = getdate()  
from datFS fs
join datAE t2
on fs.fsID= t2.fsID
join @AllCompletedNotYetDeleted t1
on fs.fsID=t1.fsID
where DateSent < DATEADD(m, -6, GETDATE())

我做错了什么?

4 个答案:

答案 0 :(得分:1)

试试这个 -

CREATE UNIQUE NONCLUSTERED INDEX ix ON dbo.datFS (DateSent, fsID)
GO

DECLARE @dt DATETIME = DATEADD(M, -6, GETDATE())

UPDATE fs
SET fs.testrun = GETDATE()
FROM datFS fs
WHERE DateSent < @dt
    AND fs.fsID IN (
        SELECT t1.fsID
        FROM @AllCompletedNotYetDeleted t1
        JOIN datAE t2 ON t1.fsID = t2.fsID 
    )
OPTION(RECOMPILE)

答案 1 :(得分:0)

试试这个:

DECLARE @date datetime = getdate()

update fs set fs.testrun = @date 
from datFS fs
join datAE t2
on fs.fsID= t2.fsID
join @AllCompletedNotYetDeleted t1
on fs.fsID=t1.fsID
where DateSent < DATEADD(m, -6, @date)

您只会调用一次日期函数,而不是您更新的每一行。

答案 2 :(得分:0)

请运行此并发布执行计划
前十名的原因只是为了让它完成并消除事务日志填满/缓慢作为问题 你做 NOT 想让with(nolock)处于活动状态 - 这只是为了测试锁争用

我相信fsID是datAE的PK?

在@AllCompletedNotYetDeleted上将fsID声明为PK 如果这个很大,甚至可以尝试#temp
查询优化器在表变量

方面表现不佳

如果索引碎片,则重建索引

ls_5min.append(ls_5min.insert((x1[i]+ l), 10))

答案 3 :(得分:0)

你的问题的答案是你想要索引。对于此查询:

select fs.fsID
from datFS fs join
     datAE t2
     on fs.fsID = t2.fsID join
     @AllCompletedNotYetDeleted t1
     on fs.fsID = t1.fsID
where DateSent < DATEADD(month, -6, GETDATE());

最佳索引是(可能)datAE(fsID)@AllCompletedNotYetDeleted(fsID)。在SQL Server 2014中,您可以在表变量上显式创建索引。在早期版本中,您可以通过创建唯一约束来隐式执行此操作。这个answer很有帮助。

包含DateSent的索引可能很有用。但是,不清楚列中的表是什么,where条件可能选择了那么多行而不使用索引。

最后,您还应该检查是否在select / update中获得重复记录 - 这样的重复记录只会浪费时间进行更新。