使用ROW_NUMBER优化删除SQL重复项

时间:2012-04-03 02:50:48

标签: tsql sql-server-2008-r2

我正在尝试使用列删除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]上的一个非聚集,但实际上增加了运行时间。

有什么方法可以进一步优化这个吗?

1 个答案:

答案 0 :(得分:0)

关键是找到删除行的最佳位置。与@numIds一起玩以找到最快的增量,然后让它流失。

这是4亿行,它不会在几分钟甚至几小时内完成整个过程,这需要时间。只要表格填充速度不快,你就可以删除欺骗,你没事。

找到最佳位置,然后安排它经常运行并且不在高峰期。然后不时检查过程,以确保甜蜜点保持甜蜜。

我能想到的另一件事是计算删除它们之外的欺骗。这将节省一些时间。特别是如果你可以在一个sql语句中计算dupe然后将该数据放入另一个表(即DupeIdsToDelete,然后对这些ID运行一个删除循环)