使用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秒。
答案 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。