如何更快地从SQL Server中的大表删除数据?

时间:2018-12-02 18:18:17

标签: c# sql-server

我有一个巨大的表(日志),其中保存一些历史数据。它有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分钟以上。

一段时间可以正常工作。但是现在我们意识到重复项太多,此过程无法足够快地删除重复项。因此,数据库的大小变得越来越大,并且过程越来越慢。

有没有办法使其更快?或某种准则?

谢谢

2 个答案:

答案 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