
1) 【一句话结论】采用“行为日志表+聚合统计表”双表设计,结合分库分表(按用户/时间分区)、多维度索引,通过实时流处理(Kafka+Flink)与离线ETL构建,兼顾实时更新与历史数据一致性,支撑按用户、课程、时间范围的查询性能优化。
2) 【原理/概念讲解】老师口吻,解释关键概念:
行为日志表是“事实表”,存储原始学习行为数据(如点击、答题、观看时长),支持实时查询与审计;聚合统计表是“维度表”,存储聚合后的统计结果(如用户答题总数、课程观看时长),用于快速多维度查询。
分库分表:垂直分库(按用户维度分库,每个用户数据集中存储,减少跨库查询延迟)+ 水平分表(按时间维度分表,如按天分表,避免单表数据过大);
索引策略:主键(唯一标识,如UUID+时间戳)+ 复合索引(按查询条件组合,如user_id+action_time、course_id+action_time);
数据一致性:实时更新通过消息队列(如Kafka)异步写入日志表(减少写入延迟);历史数据通过ETL作业(如Flink)定时同步到聚合表(保证一致性)。
类比:行为日志表像“流水账”,记录每一笔交易;聚合表像“统计报表”,快速查看总金额、交易次数。
3) 【对比与适用场景】
| 对比维度 | MySQL(关系型) | InfluxDB(时序) |
|---|---|---|
| 定义 | 支持复杂关系、事务、ACID | 专为时间序列数据设计,高写入吞吐 |
| 特性 | 强一致性、支持复杂查询(JOIN) | 高写入性能、时间索引优化、聚合函数 |
| 使用场景 | 原始行为日志(需关联用户/课程信息) | 聚合统计(如按时间聚合观看时长) |
| 注意点 | 单表数据量限制(百万级需分表) | 不支持复杂JOIN,需结合关系型数据库 |
4) 【示例】
user_action_log):CREATE TABLE user_action_log (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT NOT NULL,
course_id BIGINT NOT NULL,
action_type ENUM('click', 'answer', 'watch') NOT NULL,
action_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
duration INT, -- 观看时长(秒)
FOREIGN KEY (user_id) REFERENCES users(user_id),
FOREIGN KEY (course_id) REFERENCES courses(course_id)
) ENGINE=InnoDB;
user_course_stats):CREATE TABLE user_course_stats (
user_id BIGINT NOT NULL,
course_id BIGINT NOT NULL,
total_clicks BIGINT DEFAULT 0,
total_answers BIGINT DEFAULT 0,
total_watch_time BIGINT DEFAULT 0,
last_update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (user_id, course_id),
INDEX idx_user_course (user_id, course_id)
);
SELECT * FROM user_action_log
WHERE user_id = ? AND action_time >= DATE_SUB(NOW(), INTERVAL 7 DAY);
SELECT course_id, SUM(total_answers) AS total_answers
FROM user_action_log
WHERE action_type = 'answer'
GROUP BY course_id;
SELECT DATE(action_time) AS day, SUM(duration) AS total_watch_time
FROM user_action_log
WHERE action_type = 'watch'
GROUP BY day;
5) 【面试口播版答案】
“面试官您好,针对教育平台百万级学习行为数据存储与查询需求,我的设计思路是:首先,采用‘行为日志表+聚合统计表’双表结构,原始行为数据写入日志表,聚合数据同步到统计表,这样既保证实时查询能力,又提升聚合查询效率。然后,针对数据量增长,采用分库分表策略,按用户维度垂直分库(每个用户数据集中存储,减少跨库查询延迟),按时间维度水平分表(比如按天分表,避免单表数据过大);同时,为查询性能优化,在日志表上建立复合索引(如user_id+action_time、course_id+action_time),在聚合表上建立主键+多列索引,支撑按用户、课程、时间范围的快速查询。对于数据一致性,实时更新通过消息队列(如Kafka)异步写入日志表,减少写入延迟;历史数据通过Flink等流处理工具定时同步到聚合表,保证聚合数据与原始数据的一致性。这样设计既能满足百万级数据的存储需求,又能高效支撑多维度查询,同时保证实时更新与历史数据的一致性。”
6) 【追问清单】
7) 【常见坑/雷区】