为什么700k数据库行需要超过15秒才能加载到内存中?

时间:2014-01-22 11:40:16

标签: c# database performance

使用C#和.NET 3.5以及ADO连接或OLEDB连接,使用700k行(每行3列)填充DataTable或DataSet需要15秒。

在DB上执行实际的select语句只需不到一秒钟。 DB与查询它的机器不同,处理数据。 (也许这增加了时间?)

数据如下所示:

public class Node
{
    public DateTime Timestamp;
    public float Value;
    public string Name;
}

使用SqlDataReader并调用reader.Read(),然后手动将数据放入上述类的新实例中,将其添加到List<Node>也需要15秒。

代码如下所示:

List<Node> data = new List<Node>();
while (reader.Read())
{
   Node n = new Node();

   n.Timestamp = (DateTime)reader["Timestamp"];
   n.Value = (float)reader["Value"];
   n.NodeName = (string)reader["NodeName"];

   data.Add(n);
}

我在发布模式下使用StopWatch类测量了这一点,并在项目属性中启用了优化。

我知道它必须迭代每条记录,但我希望今天的任何机器能够在几秒钟内迭代700k记录,但不能更多。

这可能是什么原因需要15秒?我不合理地期望这会更快吗?

编辑单独执行SqlDataReader.Read()也需要15秒。

5 个答案:

答案 0 :(得分:1)

我认为问题在于你正在使用的容器。列表&lt;&gt;正在大量动态调整大小。请改为尝试以下程序: -

run query with a COUNT clause to get the number of records, only select a single column

List<Node> data = new List<Node>(count from above);

run normal query

fill List<> as above

这会阻止列表不断调整大小。

或者,要查看这是否是问题,请替换List&lt;&gt;与LinkedList&lt;&gt;因为这没有List&lt;&gt;的调整大小问题确实

答案 1 :(得分:0)

应该是您正在执行代码的数据库和机器之间的网络速度。

答案 2 :(得分:0)

循环中也会发生这种情况,即查询中的值是未装箱的。尝试GetString, GetFloat, etc methods可能是值得的,因为你有很多记录。

List<Node> data = new List<Node>();
while (reader.Read())
{
   Node n = new Node();

   n.Timestamp = reader.GetDateTime(0); // TODO: Check column numbers
   n.Value = reader.GetFloat(1);
   n.NodeName = reader.GetString(2);

   data.Add(n);
}

这些方法不会进行任何转换。

  

<强>说明

     

不进行转换;因此,检索数据   必须已经是字符串,否则会生成异常。

答案 3 :(得分:0)

我正在阅读很多猜测,这可能是正确的,但它们仍然是猜测。

如果在调试器下运行它并手动暂停几次,并且每次显示堆栈,您将使用random pausing方法。 它会告诉你究竟是什么花时间和原因 - 没有猜测。

如果您想使用分析器,您需要一个在挂钟时间内进行采样的分析器。 否则,您必须在a)为您提供行级别包含百分比的采样器和无法查看IO时间的情况下进行选择,或b)指导者,它仅为您提供功能级别的百分比。 两个人都没有告诉你为什么要花时间,只花多少钱。 无论你选择什么,都要忽视看待自我时间的诱惑,这在任何花费在子功能上的应用程序中充其量都会产生误导,而且它完全忽略了IO。

答案 4 :(得分:-1)

如果这不是代码问题,那么怀疑它与您的查询计划有关。

确保在执行查询之前设置正确的选项。它们在.NET和MSSQL上的状态相同。

之前发现导致性能损失的一个有趣选项是在SQL上启用ARITHABOIRT,在.NET上启用。

尝试在命令查询之前添加SET ARITHABORT ON。

参考: Slow performance of SqlDataReader