我有一张包含1900万条记录的表格。我想删除重复项,但我使用的查询需要很长时间,最终连接超时。
这是我正在使用的查询:
DELETE FROM [TableName]
WHERE id NOT IN
(SELECT MAX(id) FROM [TableName] GROUP BY field)
其中ID
是主键和自动增量。
我想删除field
中的重复项。
这个查询有更快的替代方案吗?
任何帮助都将不胜感激。
答案 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,以避免超时。祝你好运!