我有一个巨大的表(日志),其中保存一些历史数据。它有10列以上:
Id, Year, Month, Day, data1, data2, data3, ......
因为表很大,所以上面有很多索引。
系统不断在此表中插入大量新数据。但是,由于系统的工作方式,有时会插入重复的数据(只有id不同)。重复项的ID(仅ID)也插入到另一个表(log_existing)中。我们还有另一个服务,该服务将删除两个表中的重复项。这就是我们现在正在做的事情。
SET @TotalRows = 0;
SET @Rows = 0;
WHILE 1=1
BEGIN
DECLARE @Ids TABLE (id BIGINT);
INSERT INTO @Ids
SELECT TOP (@BatchSize) Id
FROM Log
DELETE FROM Log WHERE Id IN (SELECT id FROM @Ids)
DELETE FROM Log_Existing WHERE Id IN (SELECT id FROM @Ids)
SET @Rows = @@ROWCOUNT
IF(@Rows < @BatchSize)
BEGIN
BREAK;
END
SET @TotalRows = @TotalRows + @Rows
IF(@TotalRows >= @DeleteSize)
BEGIN
BREAK;
END
SET @Rows = 0;
END
基本上,该服务每2分钟(或5分钟,可配置)运行一次,以运行此批量删除。 @BatchSize = 2000和@DeleteSize = 1000000,通常运行2/5分钟以上。
一段时间可以正常工作。但是现在我们意识到重复项太多,此过程无法足够快地删除重复项。因此,数据库的大小变得越来越大,并且过程越来越慢。
有没有办法使其更快?或某种准则?
谢谢
答案 0 :(得分:3)
我会尽量避免在日志表中插入重复项。根据您的描述,这应该是可能的,其中包括一些使条目唯一的列(除了ID)。
一个选项是对唯一索引使用IGNORE_DUP_KEY选项。当存在这样的索引并且INSERT语句尝试插入违反索引唯一约束的行时,将忽略INSERT。参见Microsoft SQL Server Help。
CREATE TABLE #Test (C1 nvarchar(10), C2 nvarchar(50), C3 datetime);
GO
CREATE UNIQUE INDEX AK_Index ON #Test (C2)
WITH (IGNORE_DUP_KEY = ON);
GO
INSERT INTO #Test VALUES (N'OC', N'Ounces', GETDATE());
INSERT INTO #Test SELECT * FROM Production.UnitMeasure;
GO
SELECT COUNT(*)AS [Number of rows] FROM #Test;
GO
DROP TABLE #Test;
GO
答案 1 :(得分:0)
我想,如果您在带有JOIN子句的delete语句中使用像这样的东西。它应该做得更好。
DELETE Log, Log_Existing FROM Log, Log_Existing
WHERE Log.LOGID=Log_Existing.LOGID