Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何删除MS SQL 2005中除最新20000条记录以外的所有记录?_Sql Server_Sql Server 2005 - Fatal编程技术网

Sql server 如何删除MS SQL 2005中除最新20000条记录以外的所有记录?

Sql server 如何删除MS SQL 2005中除最新20000条记录以外的所有记录?,sql-server,sql-server-2005,Sql Server,Sql Server 2005,每天晚上我都要整理一张桌子,只放最新的20000张唱片。我可以使用子查询: delete from table WHERE id NOT IN (select TOP 20000 ID from table ORDER BY date_added DESC) 但这似乎效率低下,特别是如果我们以后决定保留50000条记录的话。我使用的是SQL2005,我想我可以用行数来完成它?订购并删除所有行数大于20000的?但我无法让它工作。子查询是我的最佳选择还是有更好的方法?如果它看起来效率很低,我会在

每天晚上我都要整理一张桌子,只放最新的20000张唱片。我可以使用子查询:

delete from table WHERE id NOT IN (select TOP 20000 ID from table ORDER BY date_added DESC)
但这似乎效率低下,特别是如果我们以后决定保留50000条记录的话。我使用的是SQL2005,我想我可以用行数来完成它?订购并删除所有行数大于20000的?但我无法让它工作。子查询是我的最佳选择还是有更好的方法?

如果它看起来效率很低,我会在开始寻找错误的树之前确保它效率很低


测量时间、cpu使用率、磁盘I/O等以查看其性能。我想您会发现它的性能比您想象的要好。

当然,这是一个基本情况,可以将其封装到一个过程中并使用两个sql语句—第一个语句选择最新的ID并减去20000,然后第二个语句删除ID低于此值的所有行

然而,从表面上看,这种方法似乎会导致大量碎片,这可能是创建新表、向其中插入最新20000条记录、删除旧记录和重命名新记录的一个很好的理由。甚至值得将表放在另一个数据库中,并从主数据库创建一个视图以方便访问。我本人通常倾向于使用用于数据加载和审计的表来执行此操作


在不知道您的实际数据量和行为的情况下很难判断,但从全球范围来看,您的效率低下可能会比您使用的删除方法更严重。如果你一天只收集一千条或更少的记录,那么删除和运行数据优化维护计划结合起来可能还可以,但更多的话,我会考虑更激进的方法。

当然,你的里程数会有所不同-这将取决于你从表底刮去的真实记录数量,但这里有一个选择

旁注:既然您添加了一个Date_字段,那么是否值得考虑只保留上次运行的datetime并在where子句中使用它来过滤要删除的记录?现在,不是20000条记录,而是在日志中允许X个天数。。。只是一个想法

-把我们要保存的记录放到临时档案里。 -你可以根据自己的意愿对饲养员进行分类

-使用truncate不会破坏我们的日志文件,并且使用更少的系统资源

-将我们的“保留”记录带回文件夹。。。 -这假设您没有使用标识列-如果使用,则应该 -指定字段名,而不是使用“*”并执行以下操作 -设置标识\u在上插入MyTable -在MyTable中插入从MyTestable中选择字段1、字段2、字段3 -我想那是对的

-做一个好公民

drop table #myTempTable
希望能有帮助-

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专家。

您的问题意味着您正在调整以从表中获得更好的日间性能。您是否在白天的查询中得到表格扫描?答案不是更好的索引吗?或者,您是否陷入了一个糟糕的模式


或者确实有一些非常奇怪的情况,您确实需要清除旧记录?20000是一个硬性数字吗?或者约会时间可以吗?然后,datetime列上的和索引将使修剪更加容易。

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

你说得对,只需3秒钟即可清除包含50000条记录的表。我认为IN子句效率很低,但也许这正是您实际传入ID文本列表的时候。谢谢你的帮助。是的,一个包含20000个逗号分隔ID的IN子句可能效率很低。不过,我敢打赌它仍然会在10-15秒内执行。当然,如果它同意解析这么长的字符串的话。请查看我的替代解决方案,它可以避免嵌套查询。我用60k行数据测试了3个解决方案,根据执行计划,结果是最快的。我想按照第一段中描述的方式进行测试,但假设记录ID中没有空白。我想情况会是这样的,这可能会奏效。我原本计划使用日期,比如删除所有超过2周的记录。但客户特别希望保留一个确切的数字。他的理由是,如果某些东西在几天内坏掉,我们不会意外地耗尽空间。这一个和临时表方法都是我从未想到过的好主意。我喜欢这个网站。
insert into MyTable select * from #myTempTable
drop table #myTempTable
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