
一、培训考试系统真正的性能问题可能5年以后才出现企业第一次部署培训考试系统时数据规模通常并不大。例如员工3000人 课程200门 试题30000道 每年考试200场第一年运行下来管理员可能感觉系统很快数据库也没多大。于是很容易形成一种判断“这些数据量没有什么压力。”但培训考试系统与很多一次性业务系统不同。它最大的特点是数据只会越来越多。人员可以离职但历史培训记录通常仍然需要查询。考试结束了但成绩不能随意删除。证书过期了历史证书仍然可能需要追溯。题库修改了历史答卷仍然需要保留当时的考试数据。于是系统中的数据开始不断累积第1年 ↓ 第2年 ↓ 第3年 ↓ 第5年 ↓ 第8年真正需要关注的问题已经不是系统现在有多少人而是一名员工一年会产生多少条数据二、考试系统的数据增长并不是“人数×1”假设企业有10000名员工。一年组织20次正式考试每场考试平均100道题如果每一道题都保存最终答题记录那么仅答题明细就是10000 × 20 × 100也就是2000万条这还只是最终答题记录。如果系统还记录自动保存 答案版本 Exam Session 登录日志 网络状态 切屏记录 监考记录 阅卷记录 成绩重算真实数据量会更大。培训系统同样如此。例如课程学习记录 章节完成记录 视频播放进度 学习时长 课后练习 培训计划 培训完成状态 证书 学习档案因此一套运行5年以上的培训考试系统真正的数据规模往往不能单纯按照“员工数量”估算。三、哪些数据增长最快从长期运行角度看可以把培训考试系统中的数据大致分成几类。1. 基础数据例如人员 部门 岗位 角色 课程 试题 试卷 考试 培训计划这种数据量通常相对可控。即使企业有几万人人员表本身也很少成为真正的性能瓶颈。2. 结果数据例如考试成绩 考试次数 培训完成结果 证书 课程完成状态数据量开始明显增加但一般仍然能够控制。3. 明细数据真正增长非常快的是逐题答卷 练习记录 学习章节记录 答题版本 主观题阅卷记录例如一场考试20000人 × 100道题就是200万条答题记录4. 行为日志数据增长速度可能更快。例如登录 自动保存 心跳 断网 恢复 切屏 人脸核验 监考异常 管理员操作如果设计成高频事件日志数量很容易达到千万级 甚至亿级5. 文件型数据这是另一个经常被忽视的问题。例如课程视频 PDF Word PPT 人脸照片 监考截图 证书PDF 导出Excel 考试附件它们不一定让数据库表记录数变得巨大却很容易把服务器磁盘占满。所以数据库大和磁盘大其实是两个不同的问题。四、最危险的处理方式数据大了直接DELETE很多系统运行几年以后管理员发现数据库已经非常大于是第一个想法是DELETE FROM exam_answer WHERE create_time 2022-01-01;这种操作风险非常高。因为培训考试系统的数据之间往往存在关联。例如考试成绩 ↓ 答卷 ↓ 试题 ↓ 阅卷 ↓ 证书 ↓ 一人一档如果只删除exam_answer可能导致管理员还能看到张三86分但点击查看答卷以后发现没有任何数据更加严重的是如果历史成绩 证书 培训档案 审计记录存在合规或业务追溯要求那么直接删除可能造成不可恢复的数据缺失。所以正确思路通常不是旧数据全部删除。而是旧数据退出核心业务库但仍然可以查询。这就是数据归档。五、什么叫热数据、温数据和冷数据一种比较容易落地的设计方式是把数据分成三个层次。热数据 Hot Data特点是最近 经常访问 直接参与当前业务例如本年度考试 当前培训计划 当前课程进度 最近考试成绩 当前证书要求查询快 实时修改 频繁统计因此应该保留在核心业务数据库温数据 Warm Data例如13年前考试记录 历史培训结果 已经结束但偶尔查询的数据查询频率已经明显下降但管理员仍然可能查看历史成绩 历史答卷 部门培训情况 员工档案这类数据可以继续保留在线但可以逐步采用历史表 分区表 归档库进行管理。冷数据 Cold Data例如5年前答题明细 多年以前的操作日志 历史监考图片 旧版课程附件 过期导出文件访问频率可能已经非常低。这时候继续把它们全部放在高性能业务库中成本并不划算。可以转移到归档数据库 文件归档目录 对象存储 低成本磁盘 离线备份六、最重要的一点不同数据不能使用同一个归档周期不能简单规定三年前数据全部归档。因为数据价值完全不同。例如人员主数据可能长期存在user organization department最终考试成绩通常应该长期能够快速查询exam_result答题明细可以根据年份转入历史库exam_answer自动保存版本保存价值低于最终答卷可以采用更积极的归档策略answer_version临时Excel通常不需要永久保存export_file例如7天自动删除人脸照片和监考截图需要根据实际业务要求确定保存周期但一般不建议全部以BLOB形式长期堆积在主数据库。因此真正的数据生命周期应该是Data Type Business Value Access Frequency Retention Requirement共同决定。七、考试成绩和答卷为什么应该分开设计一个非常实用的原则是结果数据保持轻量过程数据允许归档。例如考试结果表exam_result只保存user_id exam_id score pass_status submit_time exam_duration ranking certificate_id一名考生只需要一条或者少量几条结果记录。而exam_answer保存question_id answer correct_answer score answer_time可能有100条甚至更多。因此系统查询员工历史成绩时应该优先访问exam_result而不是每次重新扫描exam_answer这样即使旧答卷已经进入历史库员工档案 考试成绩 是否通过 证书仍然可以快速展示。只有用户真正点击查看历史答卷时系统才访问归档数据。这就是结果在线明细分层。八、答题明细如何归档例如当前表exam_answer包含最近两年的答题记录。历史数据可以进入exam_answer_archive_2024 exam_answer_archive_2023 exam_answer_archive_2022或者统一进入archive_exam_answer甚至使用独立Archive Database结构可以变成Application ↓ Query Router ↓ ┌──────────────┬──────────────┐ │ Current DB │ Archive DB │ │ 最近数据 │ 历史数据 │ └──────────────┴──────────────┘管理员访问最近考试Current DB管理员访问2020年的历史考试Archive DB前端甚至不需要知道数据已经发生迁移。九、数据库分区和历史归档不是一回事这两个概念容易混淆。例如MySQL或者其他数据库支持按照YEAR(create_time)进行分区p2024 p2025 p2026好处是减少部分扫描范围 方便维护 方便删除旧分区但数据本质上仍然在同一个数据库体系里。而真正的归档可能是Primary DB ↓ Archive DB甚至生产服务器 ↓ 独立归档服务器所以Partition更偏数据库内部管理Archive更偏数据生命周期管理。大型系统中二者可以同时使用。十、为什么日志尤其适合按时间分区考试日志天然具备Time Series特点。例如exam_event_log_2026_01 exam_event_log_2026_02 exam_event_log_2026_03或者2026-Q1 2026-Q2 2026-Q3因为日志查询大部分都会带时间条件WHERE exam_id ? AND event_time BETWEEN ? AND ?而很少有人需要扫描系统上线以来所有日志因此日志按照月 季度 年做时间分层通常比所有历史数据永久塞进一张超大表更容易管理。十一、Heartbeat日志千万不要无限保存假设10000人考试每10秒一次Heartbeat考试时间60分钟理论Heartbeat数量10000 × 360 360万条这还只是一场考试。如果一年100场类似考试就是非常庞大的数据量。因此Heartbeat本身应该根据业务价值重新设计。例如正常情况下连续在线没有必要永久保存每一次心跳。可以聚合成session_start last_heartbeat heartbeat_count disconnect_count只有出现异常时记录HEARTBEAT_LOST NETWORK_LOST NETWORK_RECOVER这样日志量可以大幅下降。所以控制历史数据规模并不只是数据多了以后再归档。更重要的是一开始就不要生成没有长期价值的数据。十二、附件为什么不应该直接塞进业务数据库一些早期系统会把PDF 图片 证书 Word直接存成BLOB放在数据库中。这样做开发简单但运行几年以后会产生明显问题数据库文件越来越大 备份非常慢 恢复非常慢 数据库IO压力增加 迁移困难对于大量文件型数据更合理的方式通常是数据库 ↓ 只保存文件元数据例如file_id file_name file_path file_size content_type hash create_time真正文件放在文件服务器 NAS 对象存储 独立磁盘形成Database ↓ File Metadata File Storage ↓ Physical File业务数据库只管理这个文件是谁的 在哪里 什么时候上传 Hash是多少而不是直接保存整个文件内容。十三、人脸照片、监考截图是非常典型的冷数据假设一场考试20000人每人产生5张身份/监考图片就是10万张图片假设每张300KB总量接近30GB而这还只是一场考试。如果这些文件全部永久放在应用服务器系统盘长期运行以后很容易出现磁盘空间不足所以应该明确考试业务数据与考试文件数据分开管理。例如/yyyy/mm/examId/userId/或者按照bucket/exam/year/month管理。历史图片再按照生命周期迁移到低成本存储。十四、归档不是“移动完就结束”真正可靠的数据归档应该包含多个阶段。例如数据扫描 ↓ 确定归档范围 ↓ 批量读取 ↓ 写入归档库 ↓ 数量校验 ↓ Hash/Checksum校验 ↓ 标记归档完成 ↓ 业务查询验证 ↓ 删除主库旧数据 ↓ 释放空间千万不要INSERT Archive ↓ 马上DELETE Primary中间没有任何校验。至少应该确认源数据数量 目标数据数量必要情况下还可以验证Checksum或者关键字段汇总值。十五、一个简单的归档任务可以怎样设计例如archive_task字段包括task_id data_type start_time end_time source_count archive_count status checksum create_time finish_time状态WAITING COPYING VERIFYING SUCCESS FAILED归档流程创建任务 ↓ 每批5000条 ↓ 写Archive DB ↓ 记录LastId ↓ 继续下一批 ↓ 校验 ↓ 完成不要一次INSERT INTO archive_table SELECT * FROM huge_table WHERE create_time ...然后长时间锁住大量资源。大型数据归档最好小批量、可恢复、可重试。十六、为什么建议使用ID游标而不是深分页例如SELECT * FROM exam_answer ORDER BY id LIMIT 5000000, 5000;到了几百万offset以后查询成本可能明显上升。归档任务更适合SELECT * FROM exam_answer WHERE id ? AND create_time ? ORDER BY id LIMIT 5000;每一批记录last_id下一批继续。这样即使归档任务中途停止也可以从last_id继续执行。十七、归档过程中一定要考虑“系统还在写数据”例如系统正在归档2024年以前数据与此同时2026年正式考试仍然在运行。这种场景通常问题不大。真正危险的是归档范围距离当前时间过近。例如今天是2026-08却归档2026-07某些业务可能还存在补考 成绩复核 证书生成 主观题阅卷 成绩重算因此归档最好设置Safety Window例如考试结束180天 365天以后确认业务已经稳定再进入归档流程。具体周期应该根据实际业务确定而不是机械统一。十八、历史数据归档以后一人一档怎么办这是培训考试系统非常关键的问题。用户并不关心这条数据到底在Current DB还是Archive DB管理员只希望打开员工档案以后看到2020年培训 2021年考试 2022年证书 2023年培训 2024年考试 2025年考试 2026年课程因此“一人一档”页面需要的是Unified Query例如用户查询员工A ↓ 查询Current Result 查询Archive Result ↓ 统一时间线 ↓ 返回前端可以通过Query Service屏蔽存储差异。也就是说存储可以冷热分层但用户体验不能跟着分裂。这是归档系统是否真正可用的重要标准。十九、统计报表应该避免每次扫描历史明细例如管理员查看过去5年考试通过率趋势如果每次都去扫描5亿条answer明细显然是不合理的。更适合建立Summary Table例如exam_statistics_daily exam_statistics_monthly department_exam_statistics提前保存参考人数 通过人数 平均分 最高分 最低分数据驾驶舱查询统计结果而不是实时重新计算全部底层记录。因此长期运行系统需要逐渐从明细驱动查询转向明细 聚合结果双层数据模型。二十、冷热分层的一种典型架构整个培训考试系统可以设计成┌─────────────┐ │ Application │ └──────┬──────┘ ↓ Query Service ↓ ┌──────────────────┼──────────────────┐ ↓ ↓ ↓ Hot Database Archive DB File Storage 热业务数据 历史结构化数据 图片/附件/证书 ↓ ↓ ↓ 最近考试/培训 历史答卷/日志 冷文件/对象存储同时Statistics DB或者统计表负责报表 驾驶舱 趋势分析这样业务、历史、文件、统计不再全部挤在一个数据库里面。二十一、以宏远培训考试系统为例长期运行不能只看当前数据量从企业培训考试平台的业务结构来看长期积累的数据通常并不只有考试成绩。以宏远培训考试系统的整体业务场景为例人员在系统中可能持续产生课程学习记录 培训计划记录 练习数据 正式考试成绩 逐题答卷 证书 学习档案 考试日志如果系统采用培训、练习、考试、证书和档案一体化管理那么随着使用时间增长这些数据之间还存在长期关联关系。例如员工已经调部门甚至离职管理员仍然可能需要查询当时参加了什么培训 完成了哪些课程 参加过哪些考试 成绩是多少 是否取得证书 当时属于哪个部门因此系统不能简单通过清空历史记录换取性能。更合理的方向是当前业务数据保持在线 ↓ 历史明细逐步归档 ↓ 结果数据长期可查 ↓ 文件独立存储 ↓ 档案层统一查询对于宏远这类强调培训、考试、证书和一人一档关联管理的平台而言这种设计的价值在于即使底层数据已经发生冷热分层管理员看到的仍然是一个完整的人员培训考试档案。这比单纯把“数据库压缩到更小”更重要。因为技术优化最终不能破坏业务连续性。二十二、数据库归档和数据库备份千万不要混为一谈这是非常常见的误区。Backup目标是发生故障以后恢复数据例如数据库损坏 服务器故障 勒索病毒 误删除Archive目标是减少生产库规模 但历史数据仍然可以查询因此Backup ≠ Archive把旧数据库备份成BAK文件然后删除生产数据不能简单认为已经完成了“在线归档”。因为管理员以后想查询2021年张三的答卷难道每次先恢复一个数据库显然不现实。所以真正的归档应该低频 但仍然可访问二十三、归档以后仍然必须备份即使已经有Archive DB也仍然需要Backup因为归档库损坏同样会造成历史数据丢失。完整体系应该是Primary Data ↓ Archive Primary Data ↓ Backup Archive Data ↓ Backup最好不要出现Archive 唯一副本否则它并不安全。二十四、数据归档以后为什么数据库文件没有立刻变小这是数据库维护中很常见的问题。例如删除5000万条记录以后操作系统看到的数据库文件可能仍然300GB并没有直接变成100GB因为很多数据库删除数据以后只是释放内部页面供以后重新使用并不一定立即把物理文件缩小。因此后续还可能需要表重建 空间整理 索引维护 数据库维护具体操作需要根据MySQL SQL Server PostgreSQL 国产数据库分别设计。不要在正式考试期间随意执行大型OPTIMIZE REBUILD SHRINK之类操作。二十五、什么时候应该开始做归档而不是等数据库撑不住最好的时间不是磁盘只剩10GB以后。而是在系统设计阶段就确定数据生命周期策略至少应该监控数据库总容量 单表行数 单表大小 索引大小 附件容量 每日增长量 备份耗时 恢复耗时 查询P95/P99例如发现exam_answer已经2亿条而且每月还增加1000万条这时候就应该开始规划。而不是等查询已经明显卡顿 磁盘即将满 备份需要十几个小时以后再临时处理。二十六、建议建立“数据增长预测”例如当前Database 500GB过去12个月增加240GB平均20GB/月那么如果服务器只剩300GB理论上容量风险已经可以提前预测。可以建立当前容量 月增长速度 安全空间 预计扩容时间对于私有化部署系统尤其重要。因为服务器硬盘不是无限的。二十七、运行5年以上的培训考试系统建议重点检查这10项1. 最大的10张表分别多大2. 哪些表每月增长最快3. 历史答卷是否仍然全部在主库4. 正常Heartbeat是否保存过多5. 图片和附件是不是存在数据库BLOB中6. 历史日志有没有分区或归档7. 导出Excel和临时文件有没有自动清理8. 历史统计是否仍然实时扫描明细表9. 数据库备份需要多长时间10. 如果恢复5年前某名员工档案系统还能否完整查询如果这些问题没有明确答案说明系统的数据生命周期管理可能还需要补课。二十八、一个比较实用的数据生命周期方案例如可以按照下面的思路规划01年 热数据 Primary DB 实时查询 13年 温数据 Primary / Historical Partition 低频查询 3年以上 冷数据 Archive DB 按需查询 图片附件 File/Object Storage 生命周期管理 临时导出文件 730天 自动清理这只是架构示例。真正的周期需要根据企业自身业务和数据保留要求确定。核心不是一定3年归档而是形成明确、自动、可验证的数据生命周期机制。二十九、归档方案最终应该达到什么目标一个成熟的冷热分层方案不应该只是数据库容量下降50%更重要的是同时达到核心业务库更轻最近考试和培训查询更快。历史数据没有丢5年前的考试仍然能够追溯。用户不用关心数据在哪里一人一档仍然统一展示。文件与数据库解耦大量图片附件不再拖累数据库。归档过程可恢复任务失败以后能够继续执行。数据可以校验避免“迁过去一半却不知道”。备份恢复压力降低生产数据库更加容易维护。三十、结语培训考试系统上线第一年很多人最关注并发多少 考试会不会卡 课程能不能播放 成绩能不能统计但一套真正长期运行的平台还必须回答另外一个问题用了5年以后怎么办如果每年的培训记录 考试成绩 逐题答卷 操作日志 证书 图片 附件全部永久堆积在同一个数据库和同一块磁盘里那么数据规模迟早会成为新的系统瓶颈。真正合理的思路不是数据太多 ↓ 直接删除而是识别数据价值 ↓ 划分热/温/冷数据 ↓ 结果与明细分离 ↓ 文件与数据库分离 ↓ 历史数据归档 ↓ 统一查询路由 ↓ 统计数据预聚合 ↓ 建立生命周期管理对于企业培训考试平台而言数据长期积累其实并不是坏事。因为这些数据最终能够形成培训历史 考试历史 岗位能力 证书情况 人员档案 年度趋势真正的问题在于如何让有价值的历史数据长期保留下来却又不让它拖慢今天正在运行的系统。这才是冷热分层与数据归档真正要解决的问题。