【发布时间】:2012-04-22 21:35:12
【问题描述】:
我有一个清理过程,每天需要删除表中大约 800 万行(有时更多)。此过程是用 C# 编写的,并使用 SMO 查询表索引的架构,在执行批量删除 500K 行的存储过程之前禁用它们。
我的问题是整个操作都存在于事务中。 sproc 在 TransactionScope 中执行,该 TransactionScope 配置了 TransactionScopeOption.Suppress(这与其他事物一起运行,每个都启动一个新的 TransactionScope),我认为这不会允许 Transaction,并且在 sproc 中有明确的提交点。
该过程的 C# 部分可以总结为:
try {
DisableIndexes(table);
CleanTable(table);
}
finally {
RebuildIndexes(table);
}
存储过程内部有一个循环,基本上是:
DECLARE @rowCount bigint = 1
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
WHILE @rowCount <> 0 BEGIN
DELETE TOP (@rowsPerBatch) Table
WHERE
ID <= @maxID
SET @rowCount = @@rowcount
END
昨晚这个进程在启动半小时后超时,用了半小时回滚,又花了半小时重建索引...对于零工作来说停机时间太长...=(
更新:我已经在一个小型示例数据库上运行了这个过程(并且有一个小的超时),它并不是我想象的那样。显然,该过程正在正确删除行并按照我的意愿取得进展。尽管如此,日志仍在消耗。由于我处于 SIMPLE 数据库模式,在这种情况下日志不应该不会增长吗?还是删除存储过程如此“快”,以至于我没有给实际删除行的过程提供保持日志清洁所需的时间?
【问题讨论】:
-
你为什么在你的 SP 中使用 begin tran / commit??
-
因为我想强制删除在单个事务中。我认为这是我在这里解决主要问题的遗留问题,整个存储过程在单个事务中运行......我将删除它并看看会发生什么(再次)。
-
你用什么来执行你的 SQL Batch SqlCommand?一些数据访问框架?我们不得不责备一些事情,因为 TransactionScopeOption.Suppress 应该可以工作......但这取决于框架不会破坏它。
-
当我使用 SMO 来禁用索引名称时,我正在使用 SMO 的 Database.ExecuteNonQuery() 来执行“EXEC dbo.CleanTable”。
-
尝试使用其他东西来执行它。也许SMO负责“隐藏交易”。也许你也可以在你的进程中进行事务日志备份来控制日志的大小。
标签: c# sql-server performance tsql delete-row