删除SQL中数百万条记录的最佳方法是什么?

时间:2010-12-29 20:26:46

标签: sql sql-server tsql

我有一个下表structre

Table1       Table2        Table3
--------------------------------
 sId          sId           sId
 name          x              y
  x1          x2             x3

我想删除table1中基于sId在table3中没有匹配记录的所有记录,如果表2中存在sId,则不删除table1.Ther中的记录,表1中的记录大约为20,15和10千万,table2& table3 resp。 - 我做过类似的事情

Delete Top (3000000)
        From Table1 A
        Left Join Table2 B
        on A.Name ='XYZ' and
           B.sId = A.sId
        Left Join Table3 C
        on A.Name = 'XYZ' and
           C.sId = A.sId

((我在sId上添加了索引,但没有在名称上添加。)) 但这需要很长时间才能删除记录。 有没有更好的方法来删除数百万条记录? 提前谢谢。

8 个答案:

答案 0 :(得分:9)

如果您需要删除少于40%的数据,则需要批量删除5000或10000,如果您需要更多,然后将要保留的内容转储到另一个表/ bcp中,请截断此表并插入这些行你再次在/ bcp in

中转储到另一个表中
while @@rowcount > 0
begin
Delete Top (5000)
        From Table1 A
        Left Join Table2 B
        on A.Name ='XYZ' and
           B.sId = A.sId
        Left Join Table3 C
        on A.Name = 'XYZ' and
           C.sId = A.sId
end

你可以跑去看看会发生什么的小例子

CREATE TABLE #test(id INT)

INSERT #test VALUES(1)
INSERT #test VALUES(1)
INSERT #test VALUES(1)
INSERT #test VALUES(1)
INSERT #test VALUES(1)
INSERT #test VALUES(1)
INSERT #test VALUES(1)

WHILE @@rowcount > 0
BEGIN 
DELETE TOP (2) FROM #test

END 

答案 1 :(得分:2)

删除数百万条记录的一种方法是选择新表中的剩余记录,然后删除旧表并重命名新表。您可以选择最佳方式,具体取决于您可以删除的外键并重新创建外键或截断旧表中的数据并将所选数据复制回来。

如果您只需要删除几条记录,请忽略此答案。如果您确实要删除数百万条记录,那就是这样。

答案 2 :(得分:1)

使用top子句更多是为了提高并发性,实际上可能会使代码运行得更慢。

一个建议是从派生表中删除数据: http://sqlblogcasts.com/blogs/simons/archive/2009/05/22/DELETE-TOP-x-rows-avoiding-a-table-scan.aspx

答案 3 :(得分:0)

您是否在相关表格字段中设置了适当的索引?如果不是,则删除记录可能需要很长时间。

答案 4 :(得分:0)

您正在执行的DELETE操作正在运行基础SELECT语句以查找将被删除的记录。您正在进行的操作基本上是一个简单的连接。如果优化该连接,最终的DELETE也会更快。

确保您在要进行连接的列上有索引。运行执行计划以确保它们正在使用。

答案 5 :(得分:0)

另一种方法是将要保留的数据插入另一个表中,例如Table1_good。 完成并验证后: 删除Table1然后将Table1_good重命名为Table1

这样做很脏但是有效。

答案 6 :(得分:0)

清理完数据之后,我会在table3上放置一个AFTER DELETE触发器,自动删除table1中的适用记录。通过这种方式,您可以实时清理数据,而无需删除大块数据。

答案 7 :(得分:0)

我创建一个临时表创建一个seleet并填充临时表,将索引添加到临时表并从我的表中删除我要删除的记录。然后当我做完这样的事情时,我会放弃我的临时表

Select * into #temp from mytable 

blah blah(或你的查询)

//如果你想要

添加约束

我只需将主键推入临时表

然后我会说

删除mytable 其中的主键(从#temp中选择myPrimarykey)