Gio*_*iox 7 sql-server delete sql-server-2017
我有两个表,每个表包含 2 亿条记录。我必须根据列中的整数值从它们中删除大约 7000 万条记录。
我使用以下脚本以 4000 块为单位删除它们:
DECLARE @BATCHSIZE INT, @ITERATION INT, @TOTALROWS INT, @MSG VARCHAR(500)
DECLARE @STARTTIME DATETIME, @ENDTIME DATETIME
SET NOCOUNT ON;
SET DEADLOCK_PRIORITY LOW;
SET @BATCHSIZE = 4000
SET @ITERATION = 0
SET @TOTALROWS = 0
WHILE @BATCHSIZE>0
BEGIN
SET @STARTTIME = GETDATE();
BEGIN TRANSACTION
DELETE TOP(@BATCHSIZE)
FROM [mydb].[dbo].tableA
WHERE [mydb].[dbo].tableA.Code not IN (
SELECT Code
FROM [mydb].[dbo].TableB)
SET @BATCHSIZE=@@ROWCOUNT
SET @ITERATION=@ITERATION+1
SET @TOTALROWS=@TOTALROWS+@BATCHSIZE
COMMIT TRANSACTION;
SET @ENDTIME = GETDATE();
SET @MSG = 'Iteration: ' + CAST(@ITERATION AS VARCHAR) + ' Total deletes:' + CAST(@TOTALROWS AS VARCHAR) + ' >> ' + CAST(DATEDIFF(millisecond, @STARTTIME,@ENDTIME) AS VARCHAR)
RAISERROR (@MSG, 0, 1) WITH NOWAIT
END
Run Code Online (Sandbox Code Playgroud)
表 A 包含 6 列,5 个整数和一个 NVARCHAR(64)。Code列上有索引,PK上有clusterIndex。TableB 只包含一列Code,它是一个PK。
运行脚本几个小时后,它变得非常非常慢。
开始时每次迭代在 250 毫秒内执行,然后在运行几个小时后增加到2 分钟。
数据库处于简单恢复模式。它没有被任何人使用,它在具有 256GB RAM 的专用机器上运行。
我试图每小时重建索引,缩小数据库(不是文件,因为我的用户不能)但它总是很慢。
如果我开始删除另一个表上的记录,它具有完全相同的行为,开始非常快,然后在每次迭代后增加到减慢。
如何恢复初始条件?我可以做些什么来改善删除?我试过
Dan*_*man 11
对于批量的大删除,考虑指定一个聚集索引键范围而不是使用,TOP以便在计划中可以使用聚集索引查找。下面是一个例子。
DECLARE
@BATCHSIZE INT = 4000
, @ITERATION INT = 0
, @TOTALROWS INT = 0
, @MSG VARCHAR(500)
, @STARTTIME DATETIME
, @ENDTIME DATETIME
, @StartValue int = 0
, @EndValue int = 0
, @MaxValue int = (SELECT MAX(PK) FROM [mydb].[dbo].tableA);
SET NOCOUNT ON;
SET DEADLOCK_PRIORITY LOW;
WHILE @StartValue <= @MaxValue
BEGIN
SET @EndValue = @StartValue + @BATCHSIZE;
SET @STARTTIME = GETDATE();
DELETE FROM [mydb].[dbo].tableA
WHERE [mydb].[dbo].tableA.Code NOT IN (
SELECT Code
FROM [mydb].[dbo].TableB
)
AND [mydb].[dbo].tableA.PK >= @StartValue
AND [mydb].[dbo].tableA.PK < @EndValue;
SET @TOTALROWS=@TOTALROWS+@@ROWCOUNT;
SET @ITERATION=@ITERATION+1;
SET @ENDTIME = GETDATE();
SET @MSG = 'Iteration: ' + CAST(@ITERATION AS VARCHAR) + ' Total deletes:' + CAST(@TOTALROWS AS VARCHAR) + ' >> ' + CAST(DATEDIFF(millisecond, @STARTTIME,@ENDTIME) AS VARCHAR);
RAISERROR (@MSG, 0, 1) WITH NOWAIT;
SET @StartValue = @EndValue;
END;
GO
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
797 次 |
| 最近记录: |