在SQL Server中为图表处理数百万行的最快方法

时间:2018-11-30 10:22:18

标签: sql-server charts

我们每秒都将实时数据记录到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;

这只是伪代码!我们在所有相关列上都有索引。

是否有更好,更快的方法来获取图表数据?

2 个答案:

答案 0 :(得分:0)

由于扫描表的时间随着表中的行数而增加,因此我认为Timestmp列上没有索引。像一个波纹管这样的索引可能会加快您的查询速度:

CREATE NONCLUSTERED INDEX [IDX_Timestmp] ON [LargeTable](Timestmp) INCLUDE(X, Y, Id)

请注意,创建此类索引可能会花费大量时间,并且也会影响您的插入内容。

答案 1 :(得分:0)

我认为有两种方法可以改善图表的性能:

  1. 试图提高查询的性能。
  2. 减少需要读取的数据量。

如果没有完整的DDL和执行计划,对我来说几乎不可能提高查询性能。因此,建议您减少要读取的数据量。

关键是在数据到达时以给定的粒度级别汇总组并将其存储在单独的表中,如下所示:

CREATE TABLE SummarizedData
(
   int GroupId PRIMARY KEY,
   FromDate datetime,
   ToDate datetime,
   SumX float,
   SumY float,
   GroupCount 
)

IdGroup应该等于Id/100Id/1000,具体取决于您要在组中指定多少粒度。使用较大的组,您可以获得更粗糙的粒度,但图表效率更高。

我假设LargeTable Id列单调增加,因此您可以将最后处理过的Id存储在另一个名为SummaryProcessExecutions的表中

您将需要一个存储过程ExecuteSummaryProcess

  1. 从SummaryProcessExecutions中读取LastProcessedId
  2. 读取大表上的最后一个Id并将其存储到@NewLastProcessedId变量中
  3. LargeTable汇总Id > @LastProcessedId and Id <= @NewLastProcessedId中的所有行,并将结果存储到SummarizedData表中
  4. @NewLastProcessedId变量存储到SummaryProcessExecutions表中

您可以在SQL Server代理作业中频繁执行ExecuteSummaryProcess存储过程。

我认为,按日期分组比按ID分组是更好的选择。它将简化事情。 SummarizedData GroupId列将与LargeTable Id不相关,并且您不需要更新SummarizedData行,只需插入行。 / p>