Reduce/Summarize 并替换带时间戳的记录
Reduce/Summarize and Replace Timestamped Records
我有一个 SQL table,其中包含服务器性能数据的时间戳记录。多台服务器每 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 查询来为新的汇总记录生成插入语句吗?该查询会是什么样子?
或者有更好的方法来完成这个总结工作吗?
假设您每分钟都有记录,那么您可以按 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
您可能还想考虑将汇总信息移到另一个 table 中,这样您就不会最终陷入想知道自己是否在查看 "raw" 或汇总数据。其他好处是您可以包括 MAX、MIN、STDDEV 和其他值以及 AVG。
棘手的部分是划分时间。我能想到的最好方法是从 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
它回到 DATETIME
或 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)
我有一个 SQL table,其中包含服务器性能数据的时间戳记录。多台服务器每 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 查询来为新的汇总记录生成插入语句吗?该查询会是什么样子?
或者有更好的方法来完成这个总结工作吗?
假设您每分钟都有记录,那么您可以按 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
您可能还想考虑将汇总信息移到另一个 table 中,这样您就不会最终陷入想知道自己是否在查看 "raw" 或汇总数据。其他好处是您可以包括 MAX、MIN、STDDEV 和其他值以及 AVG。
棘手的部分是划分时间。我能想到的最好方法是从 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
它回到 DATETIME
或 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)