【问题标题】:Delete Duplicates in Table with huge amount of rows删除具有大量行的表中的重复项
【发布时间】:2014-06-21 19:13:00
【问题描述】:

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

这是我正在使用的查询:

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

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

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

任何帮助将不胜感激。

【问题讨论】:

标签: sql sql-server performance duplicates


【解决方案1】:

我建议暂时在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

【讨论】:

  • 你不需要加入candidates,可以直接删除from candidates
【解决方案2】:

我的回答是对 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 中的每个循环上都“显示”,但您会经常看到 SQL 消息显示已完成数百次迭代...请耐心等待。

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-18
      • 2011-01-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多