SqlDataAdapter.Fill()超时-基础存储过程快速返回

SqlDataAdapter.Fill()超时-基础存储过程快速返回,sql,timeout,dataadapter,fill,Sql,Timeout,Dataadapter,Fill,我有一个SqlDataAdapter,它由21行数据(4列)填充。驱动它的存储过程在SQL Mgmt Studio中几秒钟后返回,但是.Fill()需要5分钟 ArrayList ret = new ArrayList(); SqlDataAdapter da = null; SqlCommand cmd = null; cmd = base.GetStoredProc("usp_dsp_Stuff"); //Returns immediately i

我有一个SqlDataAdapter,它由21行数据(4列)填充。驱动它的存储过程在SQL Mgmt Studio中几秒钟后返回,但是.Fill()需要5分钟

    ArrayList ret = new ArrayList();
    SqlDataAdapter da = null;
    SqlCommand cmd = null;  
        cmd = base.GetStoredProc("usp_dsp_Stuff"); //Returns immediately in MSSMS.
        cmd.CommandTimeout = 3600; // Set to 6 min - debug only
        base.AddParameter(ref cmd, "@Param1", ParameterDirection.Input, SqlDbType.BigInt, 8, 19, 0, theParam1);
        base.AddParameter(ref cmd, "@Param2", ParameterDirection.Input, SqlDbType.BigInt, 8, 19, 0, theParam2);
        base.AddParameter(ref cmd, "@Param3", ParameterDirection.Input, SqlDbType.Char, 1, 'C');
        da = new SqlDataAdapter(cmd);
        DataTable dt = new DataTable();
        da.Fill(dt); //Takes 5 minutes.
有什么想法吗

提前谢谢! -Chris

Fill()有时会很慢,因为.NET正在分析从过程返回的数据

使用SQL事件探查器计算执行Fill()时SQL.NET实际发送的内容

如果它正在发送大量SET语句,例如

set concat_null_yields_null on set cursor_close_on_commit off set implicit_transactions off etc... 将concat\u null\u设置为 设置光标\u关闭\u打开\u关闭 设置隐式事务 等
。。然后,将这些相同的set语句放入存储过程可能会加快速度。

谢谢您的帮助。解决方案是在存储过程使用的联接上添加with(nolock)语句:

从类别tbl c内部将dbo.categoryItem\u LNK cl与c.categoryid=cl.categoryid上的(NOLOCK)连接

我不知道为什么我们在使用SqlDataAdapter时只看到性能下降,但这一变化立即解决了问题

再次感谢,
Chris

我不想透露这个消息,但是(NOLOCK)并不是一个解决方案,它只会创建脏读、丢失/重复数据,甚至中止查询。SQL数据库中的锁是您的朋友

如果锁定(或者更糟的是,阻塞)导致其速度变慢,您可以比较通过SSM运行的连接选项和应用程序使用的连接选项。使用SQL探查器查看代码是如何执行的


如果这些字段中有任何一个是大型对象,请记住,默认情况下,SSMS只自动检索几百个字符。返回的额外数据可能是一个因素。

错误的查询计划和参数嗅探。对于一个存储的进程,尤其是一个参数会大量调整读取的行的进程,查看传入参数的错误执行计划是原因。由于设置的参数不同,SQL Management Studio中不会出现这种情况

此线程很好地总结了您的问题:

这是参数的典型情况 嗅。你的申请很可能 使用不同的集合选项(集合)运行 并使用 不同的执行计划 在SSMS中创建。什么时候发生 您的过程是调用第一个 通过应用程序创建时间 基于参数的执行计划 通过。然而,这个执行计划 可能不适合另一套 参数,这可能导致性能不佳 使用 其他一组参数。见 以下是更多详细信息和 不同的解决方案:

下面是有关计划缓存和查询计划重用的更多内部内容:


我知道这太晚了,就像7年前一样!但我今天遇到了这个问题,想和大家分享我的解决方案。在我的实例中,从SQL中提取的数据是一个表值函数。表值函数仅返回约3500行,耗时不到1秒,但在c#代码中的Fill()上超时。我不知道它是谁或者如何工作的,但是删除并重新创建函数修复了它。我认为这与.NET如何读取SQL提供的数据有关,例如,如果在报表中使用视图后对其进行更改,则需要重新创建视图。我再一次;我不能100%确定幕后发生了什么,但对我来说,这是一个快速解决方案。最近,我经历了这样一个问题:
。Fill
超时,但同一个SP在SQL Server Management Studio中速度极快。这是因为.NET应用程序创建SQL连接并使用
设置ARITHABORT OFF
,而SQL Server Management Studio默认使用
设置ARITHABORT ON
。这会导致使用两种不同的执行计划,因此无法在SQLServerManagementStudio中重现此超时。我建议您查看您的SP并进行一些更改。

这对我来说也很有效,即使从表值函数中提取了10条记录,我也会超时。我在运行查询时遇到同样的问题,但使用“WITH(NOLOCK)”没有帮助。在我的查询末尾添加“OPTION(RECOMPILE)”修复了这个问题。实际上,这取决于用例。也许你可以扩展一下
,它只会产生一个新问题
,帮助读者判断这些问题是否严重到足以引起他们自己用例的关注。这为我解决了这个问题。在我的sp开始时有一个函数调用,其中包含“楼层”和“天花板”日期参数。我删除了这个函数,并手动执行了“floor”和“天花”,它成功了。事实证明,在我们的例子中,简单地删除并重新创建存储过程就解决了这个问题。为了安全起见,我们确保(诺洛克)被包括在所有地方。SQL Server的buggy now(最好使用MongoDBPlease)今天遇到了这个问题,就是这个问题。在SSMS中添加了SET ARITHABORT OFF,并复制了我看似挂起的查询。
da = new SqlDataAdapter(cmd);
da.SelectCommand.CommandTimeout = 1800;