Mysql创建每日预聚合表
一、创建每日预聚合表(每日人脸识别统计表)
CREATE TABLE IF NOT EXISTS xy_daily_face_stats (
stat_date DATE PRIMARY KEY COMMENT '统计日期(yyyy-MM-dd)',
daily_unique_person INT NOT NULL DEFAULT 0 COMMENT '当日去重人数',
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX idx_daily_count (daily_unique_person) -- 用于查询排序优化
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='每日刷脸统计表';
二、创建增量更新存储过程
查看所有存储过程
SHOW PROCEDURE STATUS WHERE Db = 'zhgddb';
方案A:更新指定日期(灵活模式)
CREATE PROCEDURE sp_update_daily_face_stats(IN p_date DATE)
BEGIN
-- 声明变量
DECLARE v_daily_unique INT DEFAULT 0;
-- 计算指定日期的统计数据
SELECT
COUNT(DISTINCT personId)
INTO
v_daily_unique
FROM xy_importandexport_record
WHERE eventName = 'acs.acs.eventType.successFace'
AND inAndOutType = 1
AND DATE(eventTime) = p_date;
-- 插入或更新统计表(使用 ON DUPLICATE KEY UPDATE)
INSERT INTO xy_daily_face_stats (stat_date, daily_unique_person)
VALUES (p_date, v_daily_unique)
ON DUPLICATE KEY UPDATE
daily_unique_person = VALUES(daily_unique_person),
updated_at = CURRENT_TIMESTAMP;
-- 返回处理结果(可选)
SELECT CONCAT('Updated: ', p_date,
', Unique: ', v_daily_unique) AS result;
END
-- 1. 查看存储过程
SHOW CREATE PROCEDURE sp_update_daily_face_stats;
-- 3. 执行
CALL sp_update_daily_face_stats('2026-01-01');
-- 4. 验证
SELECT * FROM xy_daily_face_stats ORDER BY stat_date DESC LIMIT 10;
方案B:批量更新指定日期范围(补数据用)
CREATE PROCEDURE sp_update_date_range(IN p_start_date DATE, IN p_end_date DATE)
BEGIN
DECLARE v_current_date DATE;
DECLARE v_daily_unique INT;
SET v_current_date = p_start_date;
-- 循环处理每一天
WHILE v_current_date <= p_end_date DO
-- 计算当天数据
SELECT
COUNT(DISTINCT personId)
INTO
v_daily_unique
FROM xy_importandexport_record
WHERE eventName = 'acs.acs.eventType.successFace'
AND inAndOutType = 1
AND DATE(eventTime) = v_current_date;
-- 插入或更新
INSERT INTO xy_daily_face_stats (stat_date, daily_unique_person)
VALUES (v_current_date, v_daily_unique)
ON DUPLICATE KEY UPDATE
daily_unique_person = VALUES(daily_unique_person),
updated_at = CURRENT_TIMESTAMP;
-- 下一天
SET v_current_date = DATE_ADD(v_current_date, INTERVAL 1 DAY);
END WHILE;
SELECT CONCAT('Updated from ', p_start_date, ' to ', p_end_date) AS result;
END
-- 1. 查看存储过程
SHOW CREATE PROCEDURE sp_update_date_range;
-- 2. 删除旧存储过程
-- DROP PROCEDURE IF EXISTS sp_update_date_range;
-- 3. 执行
CALL sp_update_date_range('2026-08-06', '2026-08-06');
-- 4. 验证
SELECT * FROM xy_daily_face_stats ORDER BY stat_date DESC LIMIT 10;
三、创建事件调度器(自动执行)
3.1 开启事件调度器
-- 检查是否开启
SHOW VARIABLES LIKE 'event_scheduler';
-- 开启(临时生效)
SET GLOBAL event_scheduler = ON;
-- 永久开启(修改配置文件 my.cnf 或 my.ini)
-- 在 [mysqld] 下添加:
-- event_scheduler = ON
3.2 创建每日执行事件
每小时执行 + 只更新当天,第二天凌晨固化(推荐)
-- 1. 每小时执行:更新当天数据(实时查询用)
CREATE EVENT evt_hourly_update_today
ON SCHEDULE EVERY 1 HOUR
STARTS CONCAT(CURDATE(), ' 01:00:00')
DO CALL sp_update_daily_face_stats(CURDATE());
-- 2. 每天凌晨2点:执行昨天的数据(固化,用于历史报表)
CREATE EVENT evt_daily_finalize_yesterday
ON SCHEDULE EVERY 1 DAY
STARTS CONCAT(CURDATE() + INTERVAL 1 DAY, ' 02:00:00')
DO CALL sp_update_daily_face_stats(DATE_SUB(CURDATE(), INTERVAL 1 DAY));
执行时间线:
08-06 01:00:更新 08-06 00:00-01:00 的数据
08-06 02:00:更新 08-06 00:00-02:00 的数据(覆盖)
08-06 03:00:更新 08-06 00:00-03:00 的数据(覆盖)
...
08-06 23:00:更新 08-06 00:00-23:00 的数据(覆盖)
08-07 00:00:更新 08-06 全天数据(覆盖)
08-07 02:00:固化 08-06 的数据(最终版本)
四、 管理事件
-- 查看所有事件
SHOW EVENTS;
-- 启用事件:每小时执行:更新当天数据(实时查询用)
ALTER EVENT evt_hourly_update_today ENABLE;
-- 启用事件:每天凌晨2点:执行昨天的数据(固化,用于历史报表)
ALTER EVENT evt_daily_finalize_yesterday ENABLE;
-- 查看事件详细信息
SHOW CREATE EVENT evt_hourly_update_today;
SHOW CREATE EVENT evt_daily_finalize_yesterday;
-- 暂停事件
ALTER EVENT evt_hourly_update_today DISABLE;
-- 删除事件
DROP EVENT IF EXISTS evt_hourly_update_today;
五、业务查询SQL(毫秒级响应)
5.1 查询月度日均
SELECT
DATE_FORMAT(stat_date, '%Y-%m') AS month,
ROUND(
SUM(daily_unique_person) /
COUNT(CASE WHEN daily_unique_person > 0 THEN 1 END),
0
) AS value
FROM xy_daily_face_stats
WHERE stat_date >= DATE_FORMAT(CURDATE(), '%Y-01-01')
AND stat_date <= CURDATE()
GROUP BY DATE_FORMAT(stat_date, '%Y-%m')
ORDER BY month;