我需要在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
...
正如你所看到的,我在每个时间T(T0,T1,T2,...)中请求成对的(时间,值)元组,其中每对的查询是“在之前”的元组,并且其他“在某个时间点之后”。每个请求的时间不到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×1000个查询,每个查询大约需要12毫秒= 24秒。这对绘制图形来说太多了。此外,我有一个像素。数据库中10,000,000,000个条目的序列,带有索引等,这应该为O(log n)的每个查询提供访问时间,因此查询时间小于1毫秒的数据库很好。问题只是.NET框架,(或者可能是网络?)以及我找不到更有效解决方案的问题。)
如何解决此性能问题?
我尝试/考虑了以下方法:
(1)将序列组合到单个SqlDataReader使用“union”语句执行的单个查询时无效。我想这是因为“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
在关键字'union'附近给出错误'消息156,等级15,状态1,行2错误语法。'
每个单独的查询都可以正常工作。我有语法错误吗?感谢。
(2)我确信存储过程没有任何好处,因为在SMSS中执行单个查询的时间不到一毫秒。
答案 0 :(得分:1)
我在这里建议的是尝试在某个时间创建n个线程并且并行地进行所有查询我确信您将提高查询的性能。因为它不是一个datareader问题,它取决于例如: - 在网络数据包上 - 编组和解组结果等...... 我希望这可以帮到你
答案 1 :(得分:1)
使用联合是正确的方法,但是您需要使用子查询,因为整个联合只有一个order by
,您应该使用union all
代替union
,以便它不会删除重复项:
select [time],[value] from (select top 1 [time],[value] from [table] where [time]<='T0' and [param]='1' order by [time] desc) x
union all
select [time],[value] from (select top 1 [time],[value] from [table] where [time]>='T0' and [param]='1' order by [time] asc) x
union all
select [time],[value] from (select top 1 [time],[value] from [table] where [time]<='T1' and [param]='1' order by [time] desc) x
union all
select [time],[value] from (select top 1 [time],[value] from [table] where [time]>='T1' and [param]='1' order by [time] asc) x
union all
select [time],[value] from (select top 1 [time],[value] from [table] where [time]<='T2' and [param]='1' order by [time] desc) x
union all
select [time],[value] from (select top 1 [time],[value] from [table] where [time]>='T2' and [param]='1' order by [time] asc) x
union all
select [time],[value] from (select top 1 [time],[value] from [table] where [time]<='1453511000' and [param]='1' order by [time] desc) x
union all
select [time],[value] from (select top 1 [time],[value] from [table] where [time]>='1453511000' and [param]='1' order by [time] asc) x
答案 2 :(得分:0)
主要问题是在循环内运行查询。
你真的需要为像素或时间值绘制一个点吗?如果你想坚持逐个像素的方法,那么获得所有结果会更快,如上所述,并通过使用linq查询得到点来获得你正在绘制的时间的值。