SqlDataAdapter.Fill()超时 - 底层Sproc快速返回

时间:2009-04-20 16:47:57

标签: sql timeout dataadapter fill

我有一个SqlDataAdapter,正在填充21行数据(4列)。在SQL Mgmt Studio中,驱动它的sproc会在几秒钟内返回,但.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

7 个答案:

答案 0 :(得分:3)

我知道这已经太晚了,就像7年太晚了!但我今天遇到了这个问题,想分享我的修复。在我的实例中,从SQL中提取的数据是一个表值函数。表值函数仅返回约3500行并且花费不到1秒,但它在c#代码中的Fill()上超时。我不知道它是谁或如何工作,但删除并重新创建功能修复它。我认为这与.NET如何读取SQL提供的数据有关,就像在报告中使用它后如果对它进行更改一样需要重新创建视图的方式。再一次,我不是100%肯定幕后发生的事情,但对我来说这是一个快速解决方案

答案 1 :(得分:2)

感谢您的帮助。解决方法是在sproc使用的连接上添加(nolock)语句:

FROM category_tbl c INNER JOIN dbo.categoryItem_LNK cl WITH(NOLOCK)ON c.categoryid = cl.categoryid

我不知道为什么我们在使用SqlDataAdapter时只看到了降级,但是这个改变立即解决了这个问题。

再次感谢, 克里斯

答案 2 :(得分:2)

da = new SqlDataAdapter(cmd);
da.SelectCommand.CommandTimeout = 1800;

答案 3 :(得分:2)

最近,我确实遇到了这样的情况:.Fill超时,但是在SQL Server Management Studio中,相同的SP超级快。这是因为.NET应用程序会创建SQL连接并使用SET ARITHABORT OFF,而SQL Server Management Studio默认使用SET ARITHABORT ON。这将导致使用两个不同的执行计划,因此您无法在SQL Server Management Studio中重现此超时。我建议您看一下SP并进行一些更改。

答案 4 :(得分:1)

我不想破解新闻,但是(NOLOCK)不是解决方案,只是创建new problems,例如脏读,丢失/重复数据,甚至是中止查询。 SQL数据库中的锁是你的朋友。

如果锁定(或更糟糕的是,阻塞)导致它变慢,则比较通过SSMS运行的连接选项和应用程序使用的连接选项。使用SQL事件探查器查看代码的执行方式。

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

答案 5 :(得分:1)

错误的查询计划和参数嗅探。对于存储过程,特别是参数将疯狂调整读取行的过程,查看传入参数的错误执行计划是原因。由于SET参数不同,在SQL Management Studio中不会发生这种情况。

这个帖子很好地总结了你的问题: http://social.msdn.microsoft.com/Forums/en-US/transactsql/thread/9fd72536-f714-422a-b4c9-078e2ef365da/

  

这是参数的典型情况   嗅探。您最有可能申请   运行不同的SET选项(设置   由客户端API)并使用   不同的执行计划比一个   在SSMS中创建。会发生什么事情   你的程序是第一次调用   通过您的应用程序创建时间   基于参数的执行计划   通过。但是,这个执行计划   可能不适合另一套   参数,可能导致差   使用时执行的性能   其他一组参数。见   以下是更多细节和   不同方案:   http://pratchev.blogspot.com/2007/08/parameter-sniffing.html

     

这里有更多关于计划缓存和查询计划重用的内部结构:
  http://technet.microsoft.com/en-us/library/cc966425.aspx

答案 6 :(得分:0)

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

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

如果它发送了很多SET语句,例如

set concat_null_yields_null on
set cursor_close_on_commit off
set implicit_transactions off

etc...

..然后将那些相同的set语句放入存储过程可能加快速度。