51mee - AI智能招聘平台Logo
模拟面试题目大全招聘中心会员专区

在教育平台中,需要存储用户学习行为数据(如点击、答题、观看时长),数据量每天增长百万级。请设计数据库表结构,并说明如何优化查询性能(如按用户、按课程、按时间范围查询),以及如何处理数据一致性(如实时更新与历史数据)。

科大讯飞教育类难度:中等

答案

1) 【一句话结论】采用“行为日志表+聚合统计表”双表设计,结合分库分表(按用户/时间分区)、多维度索引,通过实时流处理(Kafka+Flink)与离线ETL构建,兼顾实时更新与历史数据一致性,支撑按用户、课程、时间范围的查询性能优化。

2) 【原理/概念讲解】老师口吻,解释关键概念:
行为日志表是“事实表”,存储原始学习行为数据(如点击、答题、观看时长),支持实时查询与审计;聚合统计表是“维度表”,存储聚合后的统计结果(如用户答题总数、课程观看时长),用于快速多维度查询。
分库分表:垂直分库(按用户维度分库,每个用户数据集中存储,减少跨库查询延迟)+ 水平分表(按时间维度分表,如按天分表,避免单表数据过大);
索引策略:主键(唯一标识,如UUID+时间戳)+ 复合索引(按查询条件组合,如user_id+action_time、course_id+action_time);
数据一致性:实时更新通过消息队列(如Kafka)异步写入日志表(减少写入延迟);历史数据通过ETL作业(如Flink)定时同步到聚合表(保证一致性)。
类比:行为日志表像“流水账”,记录每一笔交易;聚合表像“统计报表”,快速查看总金额、交易次数。

3) 【对比与适用场景】

对比维度MySQL(关系型)InfluxDB(时序)
定义支持复杂关系、事务、ACID专为时间序列数据设计,高写入吞吐
特性强一致性、支持复杂查询(JOIN)高写入性能、时间索引优化、聚合函数
使用场景原始行为日志(需关联用户/课程信息)聚合统计(如按时间聚合观看时长)
注意点单表数据量限制(百万级需分表)不支持复杂JOIN,需结合关系型数据库

4) 【示例】

  • 表结构(MySQL):
    1. 行为日志表(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;
    
    1. 聚合统计表(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)
    );
    
  • 查询优化示例:
    • 按用户查询(最近7天):
    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) 【追问清单】

  1. 如果数据量增长到千万级,如何进一步优化?
    • 回答要点:增加分库分表粒度(如按周分表),引入缓存(Redis)缓存热点数据,使用列式存储(如ClickHouse)提升聚合查询性能。
  2. 如何处理冷热数据?
    • 回答要点:将高频访问的近期数据(热数据)存储在内存数据库(如Redis)或SSD,低频访问的历史数据(冷数据)存储在HDD或对象存储(如S3),通过缓存策略(LRU)管理。
  3. 如何保证高可用?
    • 回答要点:采用主从复制(MySQL主从)+ 读写分离,消息队列集群(Kafka多副本),数据库分库分表部署多节点,确保单点故障不影响服务。
  4. 如果出现数据回滚,如何处理?
    • 回答要点:在消息队列中记录操作日志,当出现错误时,通过补偿机制(如Flink的Exactly-Once语义)回滚到错误前的状态,保证数据一致性。
  5. 是否考虑过数据安全?
    • 回答要点:对敏感数据(如用户ID)进行脱敏处理,对数据库访问进行权限控制(如RBAC),对数据传输加密(如SSL/TLS)。

7) 【常见坑/雷区】

  1. 只设计单表,未考虑分库分表,导致单表数据过大,查询性能下降。
  2. 索引设计不合理,未按查询条件建索引,导致查询慢(如按时间范围查询未建时间索引)。
  3. 只考虑实时更新,忽略历史数据一致性,导致聚合数据与原始数据不一致。
  4. 未考虑数据分区(如按时间分区),导致查询全表扫描,性能差。
  5. 未考虑高并发场景,未使用缓存或读写分离,导致系统响应慢。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1