Cra*_*ein 5 performance sql-server delete sql-server-2008-r2
我正在研究一个删除 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
Run Code Online (Sandbox Code Playgroud)
此方法会填满 tempdb 并导致磁盘也填满。
有没有更有效的方法来删除表中 90% 的数据 ex ( DELETE TOP 90 PERCENT FROM sometable)
或者
有没有办法使用批处理将 10% 的 some_table 数据插入到临时表中?像这样的东西:
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
Run Code Online (Sandbox Code Playgroud)
这个怎么样?
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
Run Code Online (Sandbox Code Playgroud)
Aar*_*and 10
我在上面的评论中提到了三个不同的想法。这是对其中至少一个的详细说明(由于自我诊断的隧道视觉,您被困在其中)。
- 好吧,您可以事先计算出占 10% 的行数,然后在您的批次中进行比较。
我正在考虑这个,但我们实际上并不需要进行比较 - 我们可以找出我们想要保留的日期时间值是什么,并删除旧行的块,直到没有剩下的行。例如:
SET NOCOUNT ON;
DECLARE
@rc INT = 1,
@cutoff DATETIME,
@batchsize INT = 10000;
;WITH x(dt) AS
(
SELECT TOP (10) PERCENT datetime_column
FROM dbo.mytable
ORDER BY datetime_column DESC
)
SELECT TOP (1) @cutoff = dt -- earliest row we want to keep
FROM x
ORDER BY dt;
WHILE @rc > 0
BEGIN
DELETE TOP (@batchsize) dbo.mytable
WHERE datetime_column < @cutoff
SET @rc = @@ROWCOUNT;
END
Run Code Online (Sandbox Code Playgroud)
您可以查看此帖子以了解一些其他方法来增强此功能。
- 您可以考虑使用 drop / select into 而不是 truncate / insert,并考虑在此操作期间使用大容量日志恢复。
我认为这将是一个有效的选择,并且应该比上面的痛苦更少。
- 您也可以只执行一项数据移动操作:
SELECT TOP 10 PERCENT cols
INTO dbo.newtable
FROM dbo.oldtable
ORDER BY datetime_column;
DROP TABLE dbo.oldtable;
EXEC sys.sp_rename N'dbo.newtable', N'dbo.oldtable', N'OBJECT';
Run Code Online (Sandbox Code Playgroud)
这个也不那么痛苦,但可以随意在其中注入一些调试,以确保在执行删除之前获得所需的数据。
请注意,在后两种情况下,可能存在约束、模式绑定视图等阻止您删除表(显然入站外键不是问题,因为您可以截断,但出站可能仍然需要待处理)。现有计划也会产生影响(删除 90% 的数据也会导致统计信息更新并使计划无效,因此实际上没有什么不同),正如@Kenneth 在下面指出的那样,您需要重新建立对新表(因此您可能希望确保您可以提前编写脚本)。