【发布时间】:2013-09-18 22:30:59
【问题描述】:
我需要在 C# 中执行一系列 SQL 查询。查询类似于以下内容:
...
select top 1 [time],[value] from [table] where [time]<='T0' and [param]='1' order by [time] desc
select top 1 [time],[value] from [table] where [time]>='T0' and [param]='1' order by [time] asc
select top 1 [time],[value] from [table] where [time]<='T1' and [param]='1' order by [time] desc
select top 1 [time],[value] from [table] where [time]>='T1' and [param]='1' order by [time] asc
select top 1 [time],[value] from [table] where [time]<='T2' and [param]='1' order by [time] desc
select top 1 [time],[value] from [table] where [time]>='T2' and [param]='1' order by [time] asc
select top 1 [time],[value] from [table] where [time]<='T3' and [param]='1' order by [time] desc
select top 1 [time],[value] from [table] where [time]>='T3' and [param]='1' order by [time] asc
...
如您所见,我为 (T0, T1, T2, ...) 中的每个时间 T 请求成对的 (time, value)-tuples,其中每对的查询是“就在之前”的元组和其他“就在”某个时间点 T 之后。每个单个请求花费的时间不到 1 毫秒(根据 SMSS 2012 Express 中的 SQL Profiler)。
在我的程序 (C#.NET) 中,我使用 SqlDataReader 执行一系列查询。但是,每个查询大约需要 12-20 毫秒,这远远超出了我的预期,这对于我的目的来说是不可接受的。在我看来,SqlDataReader 的开销是问题所在,不是吗?
到代码看起来类似于这样:
foreach (int x = 0; x < screen.width; ++x)
{
time T = pixel2time(x);
string cmd = "select top 1 [time],[value] from [table] where [time]<='" + T.ToString() + "' and [param]='1' order by [time] desc";
SqlCommand scmd = new SqlCommand(cmd, con);
// The time from here ...
SqlDataReader reader = scmd.ExecuterReader();
// ... to here takes about 12-20 milliseconds
// the same query in SQL Profiler takes
// "0 milliseconds"
if (reader.Read())
{
...
}
}
(我正在绘制一个时间值序列,并在 x 轴上为代表某个时间 T 的每个像素请求时间值元组“恰好在”T 之前和“之后”T 以确定 y 值这个像素。因此,根据屏幕/窗口宽度,我可能有大约 1000 个像素,因此有 2 x 1000 个查询,每个查询需要约 12 毫秒 = 24 秒。这对于绘制图表来说太多了。此外,我有一个数据库中具有索引等的10,000,000百万条目的序列应该为每个查询提供O(log n)的访问时间,因此查询时间小于一毫秒的数据库很好。问题只是.NET框架,(或者可能是网络?)以及我找不到更有效的解决方案的问题。)
如何解决这个性能问题?
我尝试/考虑了以下方法:
(1) 使用“union”语句将序列组合到由单个 SqlDataReader 执行的单个查询不起作用。我想这是因为“union”与“order by”语句的某种不兼容。您对此了解更多吗?
编辑:(更新)
select top 1 [time],[value] from [table] where [time]<='T0' and [param]='1' order by [time] desc
union all
select top 1 [time],[value] from [table] where [time]>='T0' and [param]='1' order by [time] asc
给出错误“消息 156,级别 15,状态 1,第 2 行关键字“联合”附近的语法不正确。”
每个单独的查询都可以正常工作。我有语法错误吗?谢谢。
(2) 我确信存储过程不会带来任何好处,因为在 SMSS 中执行单个查询的时间不到一毫秒。
【问题讨论】:
-
使用
Union All而不是union。还有,表格总共有多少行? -
谢谢,我添加了更新。我的表中正好有 10,000,000 行。
标签: c# mysql sql database ado.net