删除表中包含大量行的重复项

时间:2014-06-20 13:19:06

标签: sql sql-server performance duplicates

我有一张包含1900万条记录的表格。我想删除重复项,但我使用的查询需要很长时间,最终连接超时。

这是我正在使用的查询:

DELETE FROM [TableName]
WHERE id NOT IN 
(SELECT MAX(id) FROM [TableName] GROUP BY field)  

其中ID是主键和自动增量。 我想删除field中的重复项。

这个查询有更快的替代方案吗?

任何帮助都将不胜感激。

3 个答案:

答案 0 :(得分:2)

我建议暂时在field添加一个索引以加快速度。也许使用此语句删除(即使你的索引应该可以正常工作)。

我的语句会生成一个应删除的ID列表。假设id作为主键被索引,这可能更快。这也应该比not in好一点。

with candidates as (
    SELECT id 
         , ROW_NUMBER() over (PARTITION by field order by id desc) rn
      FROM [TableName]
)
delete 
  from candidates
 where rn > 1

答案 1 :(得分:1)

我的答案是对Brett Schneiders的一个调整,采用批量处理方法(包括一个小等待)来避免争用,并减轻爆炸性日志文件的增长。

将您的初始@batchcount设置为您认为服务器可以处理的内容 - 您还可以根据需要增加/减少等待时间。一旦@@ROWCOUNT=0,循环就会终止。

declare @batchcount int, @totalrows int
set @totalrows = 0
set @batchcount = 10000 -- set this to some initial value

while @batchcount > 0
begin
    ;with dupes as (
        SELECT id 
             , ROW_NUMBER() over (PARTITION by field order by id desc) rownum
          FROM [TableName]
    )
    delete top (@batchcount) t1
      from TableName t1
      join dupes c
        on c.id = t1.id
       and c.rownum > 1

    set @batchcount = @@ROWCOUNT --record how many just got nuked
    set @totalrows = @totalrows + @batchcount --track progress
    print cast(@totalrows as varchar) + ' rows have been deleted' -- show progress
    waitfor delay '00:00:05' -- wait 5 seconds for log writes, other queries etc
end

在SSMS的每个循环中,print语句可能不会“显示”,但每隔一段时间你就会看到SQL消息显示已完成数百次迭代......请耐心等待。

答案 2 :(得分:0)

创建另一个堆表并在其中插入要删除的ID。然后删除主表中的记录(堆表中存在的位置),每个块大小为1000-5000,以避免超时。祝你好运!