我正在尝试分批存档许多记录,而不是一次性存档。
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
答案 0 :(得分:1)
据我所知,此查询的目标是存档大量行,同时阻止其他查询。临时表可帮助您缩小要删除的记录子集。由于它有一列是群集主键,因此与另一个PK的连接将非常快。您将花费更多精力来计算和删除临时表中的更新记录。
此外,没有理由使用交易并进行批量处理。你可以做一个大的更新。结果是相同的 - 在获得第一个5k行锁(〜前五个批次更新后)之后,表将被锁定,直到COMMIT语句。使用rowlock提示不会阻止锁升级。另一方面,运行w / o事务将使其他查询有机会在每1000行批处理后继续。如果您需要确保一次性归档所有记录 - 在查询或应用程序代码中添加一些重试逻辑,以解决诸如死锁或进程中断等错误。你真的需要NOLOCK提示吗?