我们每秒都将实时数据记录到SQL Server数据库中,我们希望从1000万行或更多行中生成图表。目前,我们使用类似下面的代码。目标是获取至少1000-2000个值以传递到图表中。
在下面的查询中,我们根据从LargeTable
中挑出的数据计数,对每隔n的行进行平均。最多可以选择200.000行,但是速度太慢了。
SELECT
AVG(X),
AVG(Y)
FROM
(SELECT
X, Y,
(Id / @AvgCount) AS [Group]
FROM
[LargeTable]
WHERE
Timestmp > @From
AND Timestmp < @Till) j
GROUP BY
[Group]
ORDER BY
X;
现在,我们尝试仅从LargeTable
中选择第n行,然后对这些数据取平均值以提高性能,但这几乎需要花费相同的时间。
SELECT
X, Y
FROM
(SELECT
X, Y,
ROW_NUMBER() OVER (ORDER BY Id) AS rownr
FROM
LargeTable
WHERE
Timestmp >= @From
AND Timestmp <= @Till) a
WHERE
a.rownr % (@count / 10000) = 0;
这只是伪代码!我们在所有相关列上都有索引。
是否有更好,更快的方法来获取图表数据?
答案 0 :(得分:0)
由于扫描表的时间随着表中的行数而增加,因此我认为Timestmp列上没有索引。像一个波纹管这样的索引可能会加快您的查询速度:
CREATE NONCLUSTERED INDEX [IDX_Timestmp] ON [LargeTable](Timestmp) INCLUDE(X, Y, Id)
请注意,创建此类索引可能会花费大量时间,并且也会影响您的插入内容。
答案 1 :(得分:0)
我认为有两种方法可以改善图表的性能:
如果没有完整的DDL和执行计划,对我来说几乎不可能提高查询性能。因此,建议您减少要读取的数据量。
关键是在数据到达时以给定的粒度级别汇总组并将其存储在单独的表中,如下所示:
CREATE TABLE SummarizedData
(
int GroupId PRIMARY KEY,
FromDate datetime,
ToDate datetime,
SumX float,
SumY float,
GroupCount
)
IdGroup
应该等于Id/100
或Id/1000
,具体取决于您要在组中指定多少粒度。使用较大的组,您可以获得更粗糙的粒度,但图表效率更高。
我假设LargeTable
Id
列单调增加,因此您可以将最后处理过的Id
存储在另一个名为SummaryProcessExecutions
的表中
您将需要一个存储过程ExecuteSummaryProcess
:
LastProcessedId
Id
并将其存储到@NewLastProcessedId
变量中LargeTable
汇总Id > @LastProcessedId and Id <= @NewLastProcessedId
中的所有行,并将结果存储到SummarizedData
表中@NewLastProcessedId
变量存储到SummaryProcessExecutions
表中您可以在SQL Server代理作业中频繁执行ExecuteSummaryProcess
存储过程。
我认为,按日期分组比按ID分组是更好的选择。它将简化事情。 SummarizedData
GroupId
列将与LargeTable
Id
不相关,并且您不需要更新SummarizedData
行,只需插入行。 / p>