5

我有一个 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.

有任何想法吗?

提前致谢!-克里斯

4

8 回答 8

6
da = new SqlDataAdapter(cmd);
da.SelectCommand.CommandTimeout = 1800;
于 2017-08-03T02:51:44.523 回答
5

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

于 2018-07-17T09:48:00.660 回答
4

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

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

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

再次感谢,克里斯

于 2009-04-20T18:40:23.473 回答
3

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

于 2017-02-17T11:20:01.397 回答
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

于 2010-02-03T15:53:55.047 回答
1

我讨厌爆料,但 (NOLOCK) 不是解决方案,它只会产生新问题,例如脏读、丢失/重复数据,甚至中止查询。SQL 数据库中的锁是您的朋友。

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

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

于 2009-04-22T19:03:47.533 回答
0

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

使用 SQL Profiler 计算出在 Fill() 执行时 SQL .NET 实际发送的内容。

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

将 concat_null_yields_null 设置为
设置 cursor_close_on_commit 关闭
设置implicit_transactions 关闭

ETC...

..然后将这些相同的集合语句放入您的存储过程中可能会加快速度。

于 2009-04-20T17:04:50.627 回答
0

我使用了以下代码,其持续时间是我在 da.Fill (dt) 之前添加的 sqlCommclass.CommandTimeout,因为请求时间超过 10 分钟

   using (SqlConnection myADONETConnection = new SqlConnection(vendor.Value))
     {
        using (SqlDataAdapter da = new SqlDataAdapter("", myADONETConnection))
         {
          ..
          ..
          ..
         da.SelectCommand = sqlCommclass;
                sqlCommclass.CommandTimeout = 30000;
                 da.Fill(dt);
          }
    }
于 2022-01-27T09:03:05.457 回答