批处理中的TSQL大更新 - 由于每次循环执行,因此加入会使我更加成本

时间:2016-10-14 16:30:06

标签: sql-server tsql

我正在尝试分批存档许多记录,而不是一次性存档。

TSQL是否会为批处理中的每个循环加入两个表,TeamRoster和@teamIdsToDelete?我担心的是,如果我的临时表很大并且我不会在临时表中删除记录,那么JOIN可能会不必要地昂贵。另一方面,当我去临时从临时表中删除有多昂贵?它是由(?实际/假设的?)较小的连接来弥补我在每批中必须做的?

(可以提供更多细节/想法,但如果有帮助则会这样做。)

DECLARE @teamIdsToDelete Table
    (
        RosterID int PRIMARY KEY
    )   

--collect the list of active teamIds. we will rely on the modified date to age them out.
INSERT INTO @teamIdsToDelete
SELECT  DISTINCT tr.RosterID FROM 
        rosterload.TeamRoster tr WITH (NOLOCK)
            WHERE tr.IsArchive=0 and tr.Loaded=1 


--ageout out remaining rosters. (no cap - proved we can update more than 50k by modifying test case:
WHILE (1 = 1)
BEGIN
    BEGIN TRANSACTION

    UPDATE TOP (1000) r
    SET [Status] = 'Delete', IsArchive = 1, ModifiedDate = GETDATE(), ModifiedBy = 'abc'
    FROM rosterload.TeamRoster r with(rowlock)
    JOIN @teamIdsToDelete ttd ON ttd.rosterID = r.RosterID
    WHERE  r.[Status] != 'Delete' AND r.IsArchive != 1 AND r.ModifiedBy != 'abc' -- predicate for filtering;

    IF @@ROWCOUNT = 0 -- terminating condition;
        BEGIN
        COMMIT TRANSACTION
        BREAK
        END

    COMMIT TRANSACTION
END

1 个答案:

答案 0 :(得分:1)

据我所知,此查询的目标是存档大量行,同时阻止其他查询。临时表可帮助您缩小要删除的记录子集。由于它有一列是群集主键,因此与另一个PK的连接将非常快。您将花费更多精力来计算和删除临时表中的更新记录。

此外,没有理由使用交易并进行批量处理。你可以做一个大的更新。结果是相同的 - 在获得第一个5k行锁(〜前五个批次更新后)之后,表将被锁定,直到COMMIT语句。使用rowlock提示不会阻止锁升级。另一方面,运行w / o事务将使其他查询有机会在每1000行批处理后继续。如果您需要确保一次性归档所有记录 - 在查询或应用程序代码中添加一些重试逻辑,以解决诸如死锁或进程中断等错误。你真的需要NOLOCK提示吗?