業務常需按固定間隔(如 5 分鐘、30 分鐘、1 小時)對時間序列資料做聚合。本文提供兩種通用寫法,適用於整數時間戳與 DATETIME 欄位。
CREATE TABLE `instance` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`timestamp` INT UNSIGNED DEFAULT NULL,
`cpu` DECIMAL(8,3) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
SELECT
`timestamp` - `timestamp` % 300 AS window_start,
AVG(`cpu`) AS avg_cpu
FROM `instance`
GROUP BY window_start
ORDER BY window_start;
原理:取模運算將時間戳對齊到最近的窗口起點(向下取整)。
SELECT
queueName,
HOUR(`dt`) AS h,
FLOOR(MINUTE(`dt`) / 30) AS half_hour_bucket,
AVG(memoryUsed) AS avg_mem,
SUM(memoryUsed) AS sum_mem,
COUNT(*) AS cnt
FROM queue_resource
WHERE `dt` >= '2014-04-14 00:00:00'
GROUP BY queueName, h, half_hour_bucket
ORDER BY queueName, h, half_hour_bucket;
關鍵點:
FLOOR(MINUTE(dt) / 30) 產生 0/1 兩個桶,代表 0~29 分、30~59 分HOUR(dt) 組成完整 30 分鐘窗口UNIX_TIMESTAMP(dt) DIV 1800 統一窗口 ID-- 整數時間戳
SELECT
ts - ts % :window_sec AS window_start,
AVG(val) AS avg_val
FROM metrics
GROUP BY window_start;
-- DATETIME 欄位
SELECT
DATE_FORMAT(dt, '%Y-%m-%d %H:00:00') + INTERVAL FLOOR(MINUTE(dt) / :interval_min) * :interval_min MINUTE AS window_start,
AVG(val) AS avg_val
FROM metrics
GROUP BY window_start;
INDEX idx_dt (dt)WINDOW FUNCTION 配合 RANGE BETWEEN 實現滑動窗口