Nik*_*rts 3 sql t-sql sql-server sql-server-2005
我有此功能可删除具有超过1000万行的大表中不再需要的历史数据
DELETE FROM BigTable
WHERE DATEDIFF(month,dtmtimestamp, getdate()) > 2)
Run Code Online (Sandbox Code Playgroud)
然后,我尝试使用此方法来减少事务日志使用的空间量:
WHILE (SELECT COUNT(*) FROM BigTable WHERE DATEDIFF(month,dtmtimestamp, getdate()) > 2) > 0 BEGIN
DELETE TOP 10000 FROM BigTable
FROM BigTable
WHERE DateDiff(month,dtmtimestamp, getdate()) > 2
CONTINUE END
Run Code Online (Sandbox Code Playgroud)
这是正确的方法吗?还是我将以这种方式用完更多事务日志?
有什么好的方法提示吗?
干杯,
尼可
最终答案:
DECLARE @Remainder INT
DECLARE @ChunkSize INT
SET @Remainder = (SELECT COUNT(id) FROM BigTable WHERE dtmtimestamp < DateAdd(month, -2, getdate()))
SET @ChunkSize = CEILING(@Remainder/100) /* Divide the total into 100 parts, whole integers only */
WHILE @Remainder BEGIN
BEGIN TRANSACTION deletehistorical
DELETE TOP (@ChunkSize)
FROM BigTable
WHERE dtmtimestamp < DateAdd(month, -2, getdate());
SET @Remainder = @@ROWCOUNT;
COMMIT TRANSACTION deletehistorical
END
Run Code Online (Sandbox Code Playgroud)
CHECKPOINT命令仅告诉引擎从日志中删除完成的事务(在简单恢复模式下),并且由于此查询实际上仍在继续进行每个循环,因此仍在创建事务。因此,为了分解事务,我添加了一个BEGIN和COMMIT来强制数据库每次进行这些更改。
您应该使用两种方法EXISTS(而不是计算仍要删除的行数)(因此,一旦找到行,它就会返回):
WHILE EXISTS(SELECT * FROM BigTable WHERE DATEDIFF(month,dtmtimestamp, getdate()) > 2) BEGIN
Run Code Online (Sandbox Code Playgroud)
还是运动鞋:
select top 1 * from sysobjects /* Force @@ROWCOUNT > 0 */
WHILE @@ROWCOUNT BEGIN
DELETE TOP 10000 FROM BigTable
FROM BigTable
WHERE dtmtimestamp< DateAdd(month, -2,getdate())
CONTINUE END
Run Code Online (Sandbox Code Playgroud)
该表的唯一搜索是用于实际删除的搜索。
如果dtmtimestamp列具有有用的索引,我也讨论了您的日期逻辑。
编辑当然,正如马丁指出,无论这些地址事务日志的使用。
限制删除的策略是一种合理的策略,可以停止可怕的日志使用,但是还需要同时进行大量日志备份或截断,以允许重用旧的事务日志空间。否则,它仍然会增加日志。
如果您知道每隔15分钟就会发生一次日志备份,那么您可能想通过WAITFOR DELAY每隔“ n”次迭代来暂停循环,以使您知道以前的事务日志已被备份/清除。无论发生什么情况,只要您要删除而不是将其截断,每个已删除行的日志记录仍然会占用日志或日志备份中的空间。
如果能够使使用此系统的正常情况下的任何内容脱机,并且要保留的行数与要删除的行相比显得相形见,,则可能需要复制这些行以保存到另一个表中,请删除所有键,截断表,将保留的行复制回并重建外键。YMMV。
| 归档时间: |
|
| 查看次数: |
4279 次 |
| 最近记录: |