代码之家  ›  专栏  ›  技术社区  ›  urlreader

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

  •  0
  • urlreader  · 技术社区  · 7 年前

    我有一个巨大的表(日志),其中保存了一些历史数据。它有10多列:

    Id, Year, Month, Day, data1, data2, data3, ......
    

    因为这个表很大,所以上面有很多索引。

    系统不断向这个表中插入大量新数据。但是,由于系统的工作方式,有时会插入重复数据(只有id不同)。复制的id(仅id)也被插入到另一个表(log_现有)中。我们有另一项服务将删除两个表中的重复项。以下是我们现在正在做的事情。

    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 回复  |  直到 7 年前
        1
  •  3
  •   Thomas Weingartner    7 年前

    我会尽量避免在日志表中插入重复项。根据您的描述,这应该可以包括一些使条目唯一的列(除了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
    
        2
  •  0
  •   Gaurav    7 年前

    我认为,如果将delete语句与JOIN子句一起使用,应该是这样的。它应该做得更好。

        DELETE Log, Log_Existing FROM Log, Log_Existing 
        WHERE Log.LOGID=Log_Existing.LOGID