SQL Query删除特定行数上的最旧行?

时间:2010-04-01 14:35:14

标签: sql sql-server-2005

我有一个表,其中包含我正在编写的程序的日志条目。我正在寻找关于SQL查询的想法(我正在使用SQL Server Express 2005),它将保留最新的X数量的记录,并删除其余的。我有一个datetime列,它是日志条目的时间戳。

我认为以下内容可行,但我不确定IN子句对大量记录的性能。性能并不重要,但我可能会在第一时间做到最好。

DELETE FROM MyTable WHERE PrimaryKey NOT IN
(SELECT TOP 10,000 PrimaryKey FROM MyTable ORDER BY TimeStamp DESC)

我应该提一下,这个查询每天会运行3-4次(作为另一个进程的一部分),因此每个查询将删除的记录数量与将要记录的记录数量相比将会很小保持。

5 个答案:

答案 0 :(得分:3)

试试这个:

DECLARE @X int
SELECT @X=COUNT(*) FROM MyTable 
SET @X=@X-10000

DELETE MyTable 
WHERE PrimaryKey IN (SELECT TOP(@x) PrimaryKey 
                     FROM MyTable 
                     ORDER BY TimeStamp ASC
                    ) 

取决于你是否删除少于10,000行,如果是这样,这可能会运行得更快,因为它标识要删除的行,而不是要保留的行。

答案 1 :(得分:2)

尝试此操作,使用CTE获取行序号,然后一次只删除X行数。您可以更改此变量以适合您的服务器。

添加ReadPast表提示应防止锁定。

DECLARE @numberToDelete INT;
DECLARE @ROWSTOKEEP INT;
SET @ROWSTOKEEP = 50000;
SET @numberToDelete =1000;

WHILE 1=1
BEGIN
    WITH ROWSTODELETE AS
    (
        SELECT ROW_NUMBER() OVER(ORDER BY dtsTimeStamp DESC) rn,
            *
        FROM MyTable 

    )
    DELETE TOP (@numberToDelete) FROM ROWSTODELETE WITH(READPAST)
    WHERE rn>@ROWSTOKEEP;

    IF @@ROWCOUNT=0
        BREAK;
END;

答案 2 :(得分:1)

您拥有的查询效率高得多,并且可读。

NOT INNOT EXISTSLEFT JOIN/IS NULL更有效,但仅因为两列都不能为空。你可以read this link for a more in-depth comparison

答案 3 :(得分:1)

DELETE FROM MyTable 
WHERE TimeStamp < (SELECT min(TimeStamp) 
                   FROM (SELECT TOP 10,000 TimeStamp 
                         FROM MyTable 
                         ORDER BY TimeStamp DESC))

DELETE FROM MyTable 
WHERE TimeStamp < (SELECT min(TimeStamp) 
                   FROM MyTable 
                   WHERE PrimaryKey IN (SELECT TOP 10,000 TimeStamp 
                                        FROM MyTable 
                                        ORDER BY TimeStamp DESC))

不确定这些是否有效提升。

答案 4 :(得分:1)

这取决于你的场景(对你来说是否可行)以及你有多少行,但有一种可能更加优化的方法。

  1. 使用新名称
  2. 创建日志表的新副本
  3. 在新表格中插入原始表格中最近的10,000条记录
  4. 删除原始表(或重命名)
  5. 将新表重命名为正确的名称
  6. 这显然需要更多考虑而不仅仅是删除行(例如,如果表有IDENTITY列,则需要在新表上设置等)。但是如果你有一个大表,那么将10,000行复制到一个新表然后删除原始表会更有效,而不是试图删除数百万行而只留下10,000个。