use*_*343 104 sql-server sql-optimization sql-server-2008
我有一个大数据表.该表中有1000万条记录.
这个查询的最佳方法是什么?
Delete LargeTable where readTime < dateadd(MONTH,-7,GETDATE())
Run Code Online (Sandbox Code Playgroud)
M.A*_*Ali 178
如果要删除该表中的所有行,最简单的选项是截断表,类似于
TRUNCATE TABLE LargeTable
GO
Run Code Online (Sandbox Code Playgroud)
截断表将简单地清空表,不能使用WHERE子句来限制被删除的行,也不会触发任何触发器.
另一方面,如果你要删除超过80-90%的数据,比如说你总共有11百万行,而你想要删除1000万另一种方法就是插入这100万行(你要保留的记录) )到另一个临时表.截断此大表并插回这些1百万行.
或者,如果权限/视图或其他具有此大表作为其基础表的对象不会因删除此表而受到影响,则可以将这些相对少量的行放入另一个表中,删除此表并创建具有相同模式的另一个表并导入这些行回到这个ex-Large表.
我能想到的最后一个选项是更改数据库Recovery Mode to SIMPLE,然后使用类似这样的while循环删除较小批量的行.
DECLARE @Deleted_Rows INT;
SET @Deleted_Rows = 1;
WHILE (@Deleted_Rows > 0)
BEGIN
-- Delete some small number of rows at a time
DELETE TOP (10000) LargeTable
WHERE readTime < dateadd(MONTH,-7,GETDATE())
SET @Deleted_Rows = @@ROWCOUNT;
END
Run Code Online (Sandbox Code Playgroud)并且不要忘记将恢复模式更改回完全,我认为你必须备份以使其完全情感化(更改或恢复模式).
Fra*_*ein 75
@ m-ali的答案是正确的,但请记住,如果您不在每个块之后提交事务并执行检查点,那么日志可能会增长很多.我就是这样做的,并将这篇文章http://sqlperformance.com/2013/03/io-subsystem/chunk-deletes作为参考,包括性能测试和图表:
DECLARE @Deleted_Rows INT;
SET @Deleted_Rows = 1;
WHILE (@Deleted_Rows > 0)
BEGIN
BEGIN TRANSACTION
-- Delete some small number of rows at a time
DELETE TOP (10000) LargeTable
WHERE readTime < dateadd(MONTH,-7,GETDATE())
SET @Deleted_Rows = @@ROWCOUNT;
COMMIT TRANSACTION
CHECKPOINT -- for simple recovery model
END
Run Code Online (Sandbox Code Playgroud)
Bun*_*ter 44
您还可以使用GO +执行相同查询的次数.
DELETE TOP (10000) [TARGETDATABASE].[SCHEMA].[TARGETTABLE]
WHERE readTime < dateadd(MONTH,-1,GETDATE());
-- how many times you want the query to repeat
GO 100
Run Code Online (Sandbox Code Playgroud)
小智 9
M.Ali的这种变化对我来说很好.它会删除一些,清除日志并重复.我正在看日志的增长,下降和重新开始.
DECLARE @Deleted_Rows INT;
SET @Deleted_Rows = 1;
WHILE (@Deleted_Rows > 0)
BEGIN
-- Delete some small number of rows at a time
delete top (100000) from InstallLog where DateTime between '2014-12-01' and '2015-02-01'
SET @Deleted_Rows = @@ROWCOUNT;
dbcc shrinkfile (MobiControlDB_log,0,truncateonly);
END
Run Code Online (Sandbox Code Playgroud)
小智 9
@Francisco Goldenstein,只是一个小小的修正.设置变量后必须使用COMMIT,否则WHILE将只执行一次:
DECLARE @Deleted_Rows INT;
SET @Deleted_Rows = 1;
WHILE (@Deleted_Rows > 0)
BEGIN
BEGIN TRANSACTION
-- Delete some small number of rows at a time
DELETE TOP (10000) LargeTable
WHERE readTime < dateadd(MONTH,-7,GETDATE())
SET @Deleted_Rows = @@ROWCOUNT;
COMMIT TRANSACTION
CHECKPOINT -- for simple recovery model
END
Run Code Online (Sandbox Code Playgroud)