如何在没有事务的情况下执行sproc?

时间:2012-04-10 15:11:55

标签: c# sql-server performance tsql delete-row

我有一个清理过程,需要每天删除表中大约800万行(有时更多)。此过程使用C#编写,并使用SMO查询表索引的模式,在执行以500K行批量删除的sproc之前禁用它们。

我的问题是整个操作都在一个事务中。 sproc在TransactionScope内部执行,该事务处理器使用TransactionScopeOption.Suppress进行配置(这与其他每个启动一个新的TransactionScope的东西一起运行),我认为这不会允许事务,并且在sproc中有明确的提交点。

该过程的C#部分可归纳为:

        try {
            DisableIndexes(table);
            CleanTable(table);
        }
        finally {
            RebuildIndexes(table);
        }

并且sproc里面有一个循环,基本上是:

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数据库模式,在这种情况下,日志不应该增长吗?或者删除sproc是如此“快”,我没有给出实际删除行的进程,以保持日志清理所需的时间?

2 个答案:

答案 0 :(得分:1)

根据您的具体情况,您可以使用分区视图而不是分区表。类似的东西:

create table A
(
    X int,
    Y int,
    Z varchar(300),
    primary key (X,Y),
    check (X = 1)
)

create table B
(
    X int,
    Y int,
    Z varchar(300),
    primary key (X,Y),
    check (X = 2)
)

create table C
(
    X int,
    Y int,
    Z varchar(300),
    primary key (X,Y),
    check (X = 3)
)

go

create view ABC
as
select * from A
union all
select * from B
union all
select * from C

go

insert abc (x,y,z)
values (1,4,'test')

insert abc (x,y,z)
values (2,99,'test'), (3,123,'test')

insert abc (x,y,z)
values (3,15125,'test')

select * from abc

truncate table c

select * from abc

答案 1 :(得分:0)

如果我正确理解您的问题,您需要的是automatic sliding window和分区表。