我正在研究删除 90% 的表数据的过程,因为测试只需要 10%。
我发现的最佳方法包括将 10% 的表行存储到临时表中。
当前方法
SELECT TOP 10 PERCENT *
INTO #temp_some_table
FROM some_table (nolock)
ORDER BY some_column DESC
TRUNCATE TABLE some_table
INSERT INTO some_table
SELECT *
FROM #temp_some_table
DROP TABLE #temp_some_table
此方法正在填满 tempdb 并导致磁盘也填满。
问题
有没有更有效的方法来删除表中 90% 的数据 ex ( DELETE TOP 90 PERCENT FROM sometable
)
或者
有没有办法使用批处理将 some_table 的 10% 的数据插入到临时表中?像这样的东西:
DECLARE @r INT;
WHILE @r > 0
BEGIN
BEGIN TRANSACTION;
INSERT INTO [dbo].[##temp_cds_Basket]
SELECT TOP 10 PERCENT *
FROM [dbo].[cds_basket] s
SET @r = @@ROWCOUNT;
print @r
COMMIT TRANSACTION
END
可能的解决方案
这个怎么样?
SET NOCOUNT ON;
DECLARE @r INT;
DECLARE @TenPercentDate datetime
with cte (some_column) as (
select top 10 percent some_column from some_table (nolock) order by some_column desc
)
select @TenPercentDate = min(some_column)
from cte
select @TenPercentDate
SET @r = 1;
WHILE @r > 0
BEGIN
BEGIN TRANSACTION;
DELETE TOP (10000) from
some_table
WHERE some_column < @TenPercentDate
SET @r = @@ROWCOUNT;
print @r
COMMIT TRANSACTION;
--CHECKPOINT; -- if simple
END
--rollback
我在上面的评论中提到了三个不同的想法。这是对其中至少一个的一些详细说明(由于自我诊断的隧道视觉,您会被困在上面)。
我正在考虑这个问题,但我们真的不需要进行比较 - 我们可以找出我们想要保留的边缘的日期时间值,并删除旧行的块,直到没有剩下的行。例如:
您可以查看这篇文章,了解一些增强此功能的其他方法。
我认为这将是一个有效的选择,并且应该比上述造成的痛苦更少。
这个也没有那么痛苦,但可以随意在其中注入一些调试,以确保在执行 drop 之前获得所需的数据。
请注意,在后两种情况下,可能存在约束、模式绑定视图等阻止您删除表(显然,入站外键不是问题,因为您可以截断,但出站可能仍需要待处理)。现有计划也会产生影响(删除 90% 的数据也会导致统计信息更新和计划无效,所以没有什么不同),正如@Kenneth 在下面指出的那样,您需要重新建立对新表(因此您可能希望确保可以提前编写脚本)。
除非我遗漏了某些东西(而且我可能会遗漏!),否则这就是诀窍。