2011-11-16 48 views
2

我有一个SQL Server数据库,我使用ADO.NET ExecuteReader来获取datareader。我的存储过程返回大约35,000条记录。真的很奇怪的DataReader性能问题

对ExecuteReader的调用大约需要3秒钟才能返回数据读取器。

我正在使用与此非常相似的代码来获取我的物品。

using(var conn = new SqlConnection(MySQLHelper.ConnectionString)) { 
    conn.Open(); 
    var sqlCommand = SqlHelper.CreateCommand(conn, "spGetItems"); 
    using (var dr = sqlCommand.ExecuteReader()) { 
     while(dr.read){ 
      var item = new Item{ID = dr.GetInt32(0), ItemName = dr.GetString(1)}; 
      items.Add(item); 
     } 
    } 
} 

大部分读取操作需要0毫秒。然而,间歇性地我得到一个读取大约5.5秒(5000+毫秒)。我查看了数据,并没有发现任何不寻常的事情。我认为开始考虑那些花费这么长时间的记录的频率。

这很有趣。虽然不完全一致,但它们很接近。需要长时间加载的记录如下:

记录#:29,26,26,27,27,29,30,28,27,27,30,30,26, 27

因此,它看起来像26到30条记录将读取0到几毫秒,然后它将需要5秒,然后接下来的26到30条记录将再次按预期读取。

我在这里完全损失。我可以发布更多的代码,但没有太多。这是非常简单的代码。

编辑 我的字段都不是varchar(max),甚至是关闭的。我最大的领域是一个数字(28,12)。

修改我的存储过程后,我不再有问题。我首先将它修改为Select TOP 100,然后将其提高到Top 1000,然后是10,000,然后是100,000。我从来没有与这些问题。然后我去了TOP,现在我没有遇到我以前的问题。

+0

我发现如果我修改我的存储过程只返回100个项目,它运行良好。我将继续提高这个数字,看看是否有一个数字在性能明显下降。 –

回答

3

SqlDataReader发送给客户端的缓冲结果。见this page on MSDN for details

当结果发送回客户端时,SQL Server把尽可能多的结果集行,因为它可以为每个数据包,减少向客户端发送数据包的数量。

我怀疑你得到每个数据包26-30条记录。在遍历记录时,随着新记录的加载,您会得到延迟。

+0

这是有道理的。 –

+0

这听起来可行。但为什么需要5秒才能检索30条记录? – 2011-11-16 20:36:09

+0

@ jdv-JandeVaan不知道 - 除非它是一个高度潜在的网络连接,服务器处于压力之下,或类似的东西... –

0

什么是你阅读的表的结构?你不使用nvarchar(max)类型的第二列吗?

+0

没有列的最大。所有限制为150或更少。 –

0

在没有您的程序的情况下运行存储过程需要多长时间?我怀疑它需要很长时间才能运行,并且正如其他人指出的那样,由于缓冲,您会看到奇怪的行为。

+0

存储过程需要0.25秒到2秒的时间才能运行。 –

1

我有类似的问题。答案是使用nvarchar(max)强制转换所有文本字段,然后.NET ExecuteReader在MS Studio中执行sproc的过程中以类似的周期返回。请注意,该sproc不包含事务,但.NET调用被包装在一个事务中。