ADO.NET调用T-SQL存储过程会导致SqlTimeoutException

时间:2009-05-07 11:25:43

标签: sql-server tsql ado.net timeout output-parameter

我有一个带签名

的T-SQL存储过程
CREATE PROCEDURE MyProc
@recordCount INT OUTPUT
@param1 INT
...

直接在Sql Server中执行时,程序在5秒内运行,返回一些总计约100行的结果集。

使用ADO.NET SqlDataAdapter.Fill方法调用此过程以填充Dataset会在3分钟(指定的超时间隔)后在SqlTimeoutException上导致SqlCommand。< / p>

更改存储过程以使其不再具有输出参数,并且所需的输出值作为最后一个结果集返回,解决了问题,并且整个过程在预期的5秒内运行。

但为什么?

我不想通过我的代码库来修改这种行为的所有实例,而不理解我是否真的解决了这个问题。

另外需要注意的是,这只在一个特定的服务器上显而易见,该服务器确实拥有比我们运行的其他类似数据库更大的数据集。肯定不是Sql Server设置?

更新

进入框架源,问题似乎出现在元数据检索中。 ConsumeMetaData对象的SqlDataReader方法无限期挂起。但是我在其他数据库上运行测试并且无法重现,所以当通过ADO.NET调用此过程时,这是一个特定于数据库的问题......很棒。

更新II

如果我更改代码以使用带有SQLOLEDB或SQLNCLI提供程序类型的OleDbDataAdapter,则确认仍然会出现此问题。绝对与连接有关。

3 个答案:

答案 0 :(得分:45)

一旦我确定它是问题根源的ADO.NET连接,这个thread就引出了我的答案。

默认情况下,基本上通过Sql Server Management Studio(SSMS)连接的是SET ARITHABORT ON。 ADO.NET连接没有。

设置ARITHABORT OFF并直接通过SSMS执行查询会给我相同的慢响应时间。

使用或不使用此设置运行时的主要区别是为两个调用创建了不同的查询计划。当ARITHABORTOFF时,SSMS命令将使用ADO.NET连接正在使用的预编译缓存查询计划,因此会超时。

通过在数据库上以管理员身份运行以下命令,无论ARITHABORT设置如何,所有查询都按预期运行。

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE

我只能假设已编译的查询计划已损坏或无效。

我会在另一个thread

上解决这个问题(我已经投了答案)

感谢。

答案 1 :(得分:1)

我的立场得到了纠正 - 是的,你 CAN 同时拥有 - 一个OUTPUT参数以及一组返回的行。你每天都学到新东西: - )

至于为什么发生超时 - 嗯......很难说。一个快速的小样本对我来说很好。你可以发布你的存储过程(至少它的相关位)?

我们谈论了多少行,这些行会在这里返回?

在存储过程中的哪一点,您计算需要作为OUTPUT参数返回的行数?

如果您尝试将另一个参数MaxRows添加到您的一个SProc中作为测试并对您的数据执行SELECT TOP (@MaxRows).......该怎么办?这会很快回来吗?

马克

答案 2 :(得分:0)

简而言之 - 我通过强制SQL Server使用最合适的索引来限制lob逻辑读取来修复我的问题,当它无法自行解决时。

长 -

我遇到了这个问题并在尝试了所有其他建议的答案后以不同的方式解决了这个问题。在SSMS中,查询在~3s内运行,但是从.Net MVC Web应用程序调用时超时。

SSMS中的统计IO输出告诉我,一个表上有超过195,500,000个lob逻辑读取(具有聚簇列存储索引的20M行表,并且还有行索引,但没有“LOB”列)。我从执行计划中注意到,大部分负载(76%)来自其中一个行索引的索引查找。我使用了以下内容:

from [table] with (index([clustered columnstore index name]))

在我的查询中强制使用聚簇列存储索引,我的查询减少到&lt; 1s并且lob逻辑读取从&gt; 195M下降到<6k,并且当从Web应用程序调用SP时,它是在1.3s的往返行程。

我尝试重新编译选项,设置arithabort,参数嗅探,最后SQL Server无法确定要使用哪个索引。这是一个边缘情况太btw,我唯一一次强制在这个数据库中的索引。