SQL Server大事务,然后偶尔命令超时



我有一个导入大量数据的批处理过程。我的做法是读入一个大的文本文件,进行解析,然后根据数据的要求执行插入、更新和删除。这些都是作为存储过程执行的简单语句。存储过程调用的批处理被包装在事务中,以确保文件在继续之前被完全处理。批量导入每周执行一次。如果客户端落后,可能会连续出现几个大事务。当发生这种情况时,我偶尔会在第一个事务之后的事务中获得命令超时。我已将命令超时时间增加到120秒。到目前为止运行良好,但在一台速度较慢的计算机上,可能就不行了。我注意到超时经常发生在:

Update <table> set <columns> where <pk = some value>

我想也许SQL还在后台更新索引。你知道是怎么回事吗?

我意识到我可以使用SqlBulkCopy这样的东西,但是,这不是一个选项,现在。

谢谢,斯科特

您的程序是逐行执行还是基于集合执行insert、UPDATES等操作?这个问题的答案在几段之后会变得很重要。

但首先,扩展超时的问题是n+1的问题,不管你让它多长时间都会有超时的情况。因此,延长休息时间并不是一个长久之计。更好的方法是通过分解作业来消除对超时的需要。

你要做的第一件事是消除包装事务。维护锁所需的资源会随着操作中的行数的增加而激增,因此,如果将这样的批处理操作分解为需要更小事务的更小的步骤,通常会更快。

由于不再有包装事务,下一步是确保在作业失败的情况下,无论进程在哪里失败,都可以安全地重新运行每个单独的步骤。如果你想花哨一点,这就叫做"幂等的",如果你想用通俗的英语,这就叫做"可重新运行的"。

现在我们回到问题,您的进程是逐行执行还是执行影响许多行的insert,然后是UPDATES,等等。

CASE ROW-BY-ROW:最简单,但可能是最慢的。将文本文件放入"INBOX"表中,并添加列"Processed",即Y/N。在逐行操作时,执行INSERT、UPDATE或DELETE操作,然后将收件箱表中的行更新为Processed=Y。如果在任何阶段拔掉插头,进程都会继续查看未处理的行,直到没有行剩余为止。这给您提供了与大包装事务相同的效果,但没有额外的开销。你可以连续运行几十个文件,服务器永远不会超时。

CASE SET-BASED:如果使用的是基于集合的DML,则修改INSERT,使其从INBOX表中提取并插入目标表中尚未存在的所有行。这使得它可重新运行。DELETE语句不需要这种检查,如果您重新运行一个基于集合的DELETE语句,并且它已经运行过了,它只是找不到任何可删除的内容。中的UPDATE基本上与DELETE相同。

这是基于你所陈述的问题的一般性建议。为了得到更具体的我需要知道更多的过程

我会查看索引的碎片并在必要时重建它们。

我还会在SSMS中运行您的查询,并打开包括实际执行计划,看看您是否有任何问题。

您需要首先调查导致超时的原因。对于任何SQL Server性能调查,最好的方法是等待和队列方法。基本上,您需要查看sys.dm_exec_requests中的wait_type, wait_timewait_resource,以进行UPDATE的会话。这将显示是什么阻碍/减慢了更新,并根据这一发现,您可以采取适当的行动/解决方案。如果我大胆猜测的话,您在测试中遇到了日志自动增长事件。尽管如此,正确的解决方案是先测量后切断:调查以确定超时的根本原因,然后再进行更改。

最新更新