清除工作优化

时间:2016-08-11 15:10:14

标签: sql-server tsql sql-server-2012 sql-server-2008-r2

SQL Server 2008 R2企业版

我有一个包含3个表的数据库,我保留15天的保留时间。这是一个非常活跃的日志数据库,大小约为500 GB,除非被清除,否则每天大约吃30GB。我似乎无法陷入其中一张桌子而且落后了。这个表有2.2亿行,每晚需要清除大约1000万到1200万行。我目前需要清除3000万行。我只能在晚上运行此清洗,因为传入的刀片会竞争表锁。我已经确认所有内容都已正确索引并运行Brent Ozars sp_Blitz_Index只是为了确认。有没有办法优化我在下面做的事情?我正在为每个表运行相同的清除步骤。

  1. 删除并创建3个清除表:Purge_Log,Purge_SLogHeader和Purge_SLogMessage。
  2. 2.将行插入清除表(每个表占用5分钟):

    Insert Into Purge_Log
    Select ID from ServiceLog 
    where startTime <  dateadd (day, -15, getdate()  )
    

    - ********************************************* *******

    Insert into Purge_SLogMessage
    select serviceLogId from ServiceLogMessage 
    where serviceLogId in ( select id from 
                           ServiceLog 
                           where startTime <  dateadd (day, -15, getdate() ))
    

    - ********************************************* *******

    Insert into Purge_SLogHeader
    Select serviceLogId from ServiceLogHeader
    where serviceLogId in ( select id from 
                           ServiceLog 
                           where startTime <  dateadd (day, -15, getdate()  ))
    

    在插入之后,我运行以下每个表的差异:

    SET ROWCOUNT 1000
    
    delete_more:
    delete from ServiceLog
    where Id in ( select Id from Purge_Log)
    
    IF @@ROWCOUNT > 0 GOTO delete_more
    SET ROWCOUNT 0     
    

    基本上任何人都会看到一种方法,我可以让这个程序运行得更快,或者采用不同的方式来实现它。我使查询尽可能简单,只有一个子查询。我已经使用了连接,执行查询计划表示时间与完成它的时间相同。任何指导将不胜感激。

1 个答案:

答案 0 :(得分:2)

您可以对所有表使用此技术,首先在临时表中收集ID,以避免在大量数据中反复扫描原始表。我希望它能完美地适用于你所有的表格:

DECLARE @del_query VARCHAR(MAX)

/ * 从ServiceLog表而不是Purge_Log获取ID,因为Purge_Log可能由于频繁清除而具有比预期更多的数据  * /

IF OBJECT_ID('tempdb..#tmp_log_ids') IS NOT NULL DROP TABLE #tmp_log_ids
SELECT ID INTO #tmp_log_ids FROM ServiceLog WHERE startTime < DATEADD(DAY, -15, GETDATE())

SET @del_query ='
DELETE TOP(100000) sl
FROM ServiceLog sl 
INNER JOIN #tmp_log_ids t ON t.id = s1.id'
WHILE 1 = 1
BEGIN
    EXEC(@del_query + ' option(maxdop 5) ')
    IF @@rowcount < 100000 BREAK;
END 

SET @del_query ='
DELETE TOP(100000) sl
FROM ServiceLogMessage sl 
INNER JOIN #tmp_log_ids t ON t.id = s1.serviceLogId'
WHILE 1 = 1
BEGIN
    EXEC(@del_query + ' option(maxdop 5) ')
    IF @@rowcount < 100000 BREAK;
END

SET @del_query ='
DELETE TOP(100000) sl
FROM ServiceLogHeader sl 
INNER JOIN #tmp_log_ids t ON t.id = s1.serviceLogId'
WHILE 1 = 1
BEGIN
    EXEC(@del_query + ' option(maxdop 5) ')
    IF @@rowcount < 100000 BREAK;
END