我正在尝试使用列删除SQL表[InfoBucket]中的冗余行:
[ID] (varchar(16)), [column1], ... [columnN], [Speed] (bigint)
([column1 ... N]是从整数到不同长度的varchar()对象的数据类型。)
表中有些行在[ID]和某些[column1 ... N]列中具有相同的值。 我正在接受所有这些重复项并删除除了[Speed]之外的所有行。
[InfoBucket]中有大约4亿行。
要将工作分成可管理的块,我有另一个表,[UniqueIDs],有一列:
[ID](varchar(16))
,其填充方式如下:
begin
insert into [UniqueIDs]
select distinct [ID] from [InfoBucket]
end
go
[UniqueIDs]中约有1500万行。
我一直在使用Martin Smiths对similar question的优秀答案:
我的程序目前看起来像这样:
begin
declare @numIDs int
set @numIDs = 10000
;with toRemove as
(
select ROW_NUMBER over (partition by
[ID],
[column1],
...
[columnN]
order by [Speed] desc) as 'RowNum'
from [InfoBucket]
where [ID] in
(
select top (@numIDs) [ID] from [UniqueIDs] order by [ID]
)
)
delete toRemove
where RowNum > 1
option (maxdop 1)
;
;with IDsToRemove as
(
select top (@numIDs) [ID] from [UniqueIDs] order by [ID]
)
delete IDsToRemove
option (maxdop 1)
end
go
[ID]
和[InfoBucket]
中的[UniqueIDs]
都有非聚簇索引,而over子句中的“partition by ...”只包含需要比较的列。
现在,我的问题是这个程序运行需要六分多钟。调整@numIDs
的值会以线性方式更改运行时间(即,当@numIDs
的值为1,000时,过程运行大约36秒(6分钟/ 10)并且{{1}过程运行大约10小时(6分钟* 100);值为1,000,000;这意味着删除[InfoBucket]中的所有重复项需要数天。
我已尝试向@numIDs
添加uniqueidentifier
列[UI_ID]
并在其上创建聚簇索引(因此[InfoBucket]
在[InfoBucket]
上有一个聚簇索引和[ID]上的一个非聚集,但实际上增加了运行时间。
有什么方法可以进一步优化这个吗?
答案 0 :(得分:0)
关键是找到删除行的最佳位置。与@numIds一起玩以找到最快的增量,然后让它流失。
这是4亿行,它不会在几分钟甚至几小时内完成整个过程,这需要时间。只要表格填充速度不快,你就可以删除欺骗,你没事。
找到最佳位置,然后安排它经常运行并且不在高峰期。然后不时检查过程,以确保甜蜜点保持甜蜜。
我能想到的另一件事是计算删除它们之外的欺骗。这将节省一些时间。特别是如果你可以在一个sql语句中计算dupe然后将该数据放入另一个表(即DupeIdsToDelete,然后对这些ID运行一个删除循环)