0

我有一个 SQL 表,其中包含服务器性能数据的时间戳记录。多台服务器每 1 分钟轮询一次并存储此数据。我想长时间保留数据,但减少超过六个月的数据记录数。

例如,我有一些像这样的旧记录:

    Timestamp  Server  CPU  App1  App2
1   ... 00:01  Host1   5    1     10    
2   ... 00:01  Host2   10   5     20
3   ... 00:02  Host1   6    0     11
4   ... 00:02  Host2   11   5     20
5   ... 00:03  Host1   4    1     9
6   ... 00:04  Host2   9    6     19

对于旧数据,我希望能够将这些数据从每分钟减少到每 10 分钟或可能每小时。

我最初的假设是,我会平均 10 分钟内的时间值,并在删除旧记录后创建一个新的时间戳记录。我可以创建一个为新汇总记录生成插入语句的 sql 查询吗?该查询会是什么样子?

或者有没有更好的方法来完成这个总结工作?

4

2 回答 2

1

假设您每分钟都有记录,这就是您可以按 10 分钟对记录进行分组的方法:

SELECT
    [Timestamp] = MIN([Timestamp]),
    [Server],
    CPU = AVG(CPU),
    App1 = AVG(App1),
    App2 = AVG(App2)
FROM (
    SELECT *,
        RN = (ROW_NUMBER() OVER(PARTITION BY [Server] ORDER BY [Timestamp]) - 1) / 10
    FROM temp
)t
GROUP BY [Server], RN
于 2015-07-09T00:34:41.080 回答
1

您可能还想考虑将汇总信息移动到不同的表中,这样您就不会最终陷入想知道您正在查看的是“原始”数据还是汇总数据的情况。其他好处是您可以在 AVG 中包含 MAX、MIN、STDDEV 和其他值。

棘手的部分是划分时间。我能想到的最好方法是从CONVERT(blah, Timestamp, 120)函数的输出开始:

-- Result: 2015-07-08 20:50:55
SELECT CONVERT(VARCHAR(19), CURRENT_TIMESTAMP, 120)

通过在一小时后或 10 分钟后将其切断,您可以截断时间:

-- Hour; result is 2015-07-08 20
SELECT CONVERT(VARCHAR(13), CURRENT_TIMESTAMP, 120)

-- 10-minute point; result is 2015-07-08 20:50:5
SELECT CONVERT(VARCHAR(15), CURRENT_TIMESTAMP, 120)

稍微按摩一下,您可以填写其中任何一个的分钟数,CAST然后返回 a DATETIMEor DATETIME2

-- Hour increment
CAST(CONVERT(VARCHAR(13), CURRENT_TIMESTAMP, 120) + ':00' AS DATETIME)

-- 10-minute increment
CAST(CONVERT(VARCHAR(15), CURRENT_TIMESTAMP, 120) + 0' AS DATETIME)

使用上面的逻辑,所有时间都被截断。换句话说,小时公式会将Timestamp地点转换11:00 <= Timestamp < 12:00为 11:00。分钟公式会将Timestamp地点转换11:20 <= Timestamp < 11:30为 11:20。

所以更好的部分查询看起来像这样(我已经忽略了你刚刚总结的行):

-- The hour-increment version
INSERT INTO myTableOrOtherTable
SELECT
  CAST(CONVERT(VARCHAR(13), [Timestamp], 120) + ':00' AS DATETIME),
  AVG(CPU),
  AVG(App1),
  AVG(App2)
FROM myTable
GROUP BY
  CAST(CONVERT(VARCHAR(13), [Timestamp], 120) + ':00' AS DATETIME)
于 2015-07-09T01:08:30.103 回答