磁盘空间不足时从表中删除多行

时间:2012-03-23 02:08:21

标签: sql-server sql-server-2005

我需要从一个有大约600万行的表中删除大约500万行,因为我没有磁盘空间。有没有快速删除它们的方法?我试过在批处理上调用delete,但是运行需要很长时间,有时它会因为锁而抛出错误而且什么都不做。

编辑:

我正在进行类似

的查询
delete from <table> where updated_timestamp < '2012-02-20'

现在,为了获得更小的批次,查询如下

delete from <table> where id < [100000 row increments]

我得到的错误是它无法锁定表格。我目前没有确切的文字,但是如果我再次遇到它,我会把它粘贴在这里

4 个答案:

答案 0 :(得分:2)

删除行的唯一方法是DELETE FROM <table> WHERE <some condition>,或删除TRUNCATE TABLE <table>DROP TABLE <table>的所有行(然后重新创建)。

我没有提供任何可以提供更具体答案的信息,我担心。您可以使用WHERE子句中的条件在较小的行集(批处理)中执行此操作。 (“有时会抛出错误”对帮助你解决它没有用,顺便说一下,因为“抛出错误”没有关于“错误”可能是什么的信息是没有意义的。)

答案 1 :(得分:1)

我的建议是在您的情况下选择要保留在一个可靠的“临时”表中的百万条记录,然后截断表格,因为当您删除记录时,它会将您删除的所有记录记录到日志中额外的磁盘空间。截断表后,将实体“temp”表中的记录添加回原始表中,并删除实体“temp”表。

您可以做的其他事情是在数据库上运行CHECKPOINT,然后将其缩小。它应该释放磁盘上的一些空间。

答案 2 :(得分:0)

前两个答案绝对正确,你应该相信它。

您正在寻找的是以下

SELECT * INTO into #temp FROM <table> WHERE updated_timestamp >= '2012-02-20'
TRUNCATE TABLE <table>
INSERT INTO <table> SELECT * FROM #temp

如果你(a)有引用表的外键,或者(b)有标识列,这会变得有点复杂。对于前者,您需要通过外键约束删除引用表中记录的所有记录,删除约束,然后截断并重新创建外键。对于后者,您可以使用以下内容作为insert语句:

SET IDENTITY INSERT <table> ON
INSERT INTO <table> (<field_list>)
SELECT <field_list>) FROM #temp
SET IDENTITY INSERT <table> ON

答案 3 :(得分:0)

以下是删除日志表的代码,其中日志超过一年。批处理循环。

declare @batch int
declare @i int
declare @j int 
set @batch = 1000 
set @j = (select (COUNT(*)/@batch) + 1  from LOG_TABLE 
                where ACCESS_DATE <  dateadd(year,-1,getdate()))
set @i = 0
print @j

while (@i < @j)
BEGIN



delete top (@batch)
from LOG_TABLE 
where ACCESS_DATE < dateadd(year,-1,getdate())
SET @i = @i + 1
END