2008-11-12 73 views
6

每天晚上我都需要修剪一张表格,只包含最新的20,000条记录。我可以使用子查询:如何删除MS SQL 2005中最新的20,000条记录?

delete from table WHERE id NOT IN (select TOP 20000 ID from table ORDER BY date_added DESC) 

但这似乎效率低下,尤其是如果我们以后决定保留50,000条记录。我使用的SQL 2005,并认为我可以使用ROW_NUMBER()OVER以某种方式做到这一点?订购它们并删除所有ROW_NUMBER大于20,000的商品?但我无法实现它的工作。子查询是我最好的选择还是有更好的方法?

回答

7

如果它只是似乎低效率,我会确保它是低效的,然后我开始吠叫错误的树。

衡量时间,cpu使用情况,磁盘I/O等,看看它的表现如何。我想你会发现它比你想象的要好。

+0

你是对的,它唯一的服用3秒清除表约50,000记录在里面。我认为IN()子句非常低效,但也许就是当你实际传入一个文本ID列表时。谢谢您的帮助。 – 2008-11-12 22:37:34

+0

是的,一个包含20,000个以逗号分隔的ID的IN()子句可能效率很低。不过,我敢打赌它仍然会在10-15秒内执行。 – MusiGenesis 2008-11-12 22:40:14

+0

这就是,如果它同意甚至解析一个字符串,当然很长。 – MusiGenesis 2008-11-12 22:40:50

0

当然,这是包装进程序和使用两个sql语句的首要情况 - 第一个选择最新的ID并减去20,000,然后第二个删除ID低于此的所有行。

然而,它的表面上听起来就像你会用这种方法结束大量的碎片,这可能是创建新表的一个很好的参数,将最新的20,000条记录插入它,删除旧的并重命名新的。将表放在不同的数据库中并创建主数据库的视图以方便访问可能是值得的。我自己通常倾向于使用用于数据加载和审计的表执行此操作。

在不知道实际数据量和行为的情况下很难分辨出来,但很可能是因为全球范围内您的低效率会比您使用的删除方法更多。如果您每天只收集一千条或更少的记录,那么删除可能与运行数据优化维护计划相结合,但更多的是,我会考虑更激进的方法。

3

当然,你的里程会有所不同 - 这取决于你从这张桌子底部刮掉了多少实际记录,但这里有一个选择。

注意:由于您有一个“Date_Added”字段,是否值得考虑只保留上次运行的日期时间并在where子句中使用该日期来过滤要删除的记录?现在,而不是20,000条记录,允许在日志中的天X个...只是一个想法...


- 让我们希望保持到一个临时的记录。
- 您可以根据自己的意愿对看门人进行分类。

select top 20000 * into #myTempTable from MyTable ORDER BY DateAdded DESC 

- 使用截断不垃圾我们的日志文件,并使用更少的资源SYS ...

truncate table MyTable 

- 把我们的 '保存' 记录回折...
- 假定您不使用标识列 - 如果你是,你应该
- 指定的字段名称,而不是使用“*”,并完成类似
- SET IDENTITY_INSERT MyTable的ON
- 插入MyTable的从#myTempTable
选择场,场2,场3 - (我认为这是正确的)

insert into MyTable select * from #myTempTable 

- 成为一个好公民。

drop table #myTempTable 


希望它能帮助 -

3
DECLARE @limit INT 
SELECT @limit = min(id) FROM 
    (SELECT TOP 20000 id FROM your_table ORDER BY id DESC)x 
DELETE FROM your_table where id < @limit 

的一点是避免嵌套查询,我可能会或可能不会进行优化(抱歉不是SQL大师。 )

0

你的问题意味着你正在调整从表中获得更好的日间表现。你是否在日间查询中获得表扫描?没有更好的索引是答案?或者你是否陷入了一种“糟糕的模式”?

或者确实有一些确实需要清除旧记录的非常奇怪的情况? 20,000是难以置信的数字吗?或者日期时间可以工作?然后,日期时间列上的索引将使裁剪更容易一些。

1

插入到20000临时表中,然后删除主表中的所有记录然后再插入从临时表中 20000记录到主表..,