数据为什么需要归档
业务跑几年,订单表、日志表、流水表动辄上亿行。数据越来越多,问题一串串冒出来:查询越来越慢,因为索引和缓冲池都喂不饱大数据量;备份越来越重,全量备份时间从小时级变成天级;历史数据挤占了热数据的缓存空间,明明只查最近三个月,却被五年前的数据拖慢。
归档的本质是给数据分级:把还在被频繁访问的"热数据"留在原表,把很少访问、只为合规留存或偶尔追溯的"冷数据"移到归档区。数据总量不变,但热库变轻了,性能、备份、运维全部受益。
- 热数据高频访问,留在原表。
- 冷数据低频访问,移入归档区。
- 分区表按时间分区,便于裁剪与搬移。
- 生命周期定义数据的产生、归档与销毁。
冷热分层与访问模式
冷热分层的第一步是摸清访问模式:哪些表的数据只在最近 N 天被查?哪些表的历史数据只有对账、审计时才被碰?通过慢日志与查询统计就能画出热度曲线。常见规律:订单与流水按时间衰减,近 90 天占查询九成;日志类数据近 30 天之后几乎无人问津。
分层不是一刀切,可以按温度分多档:热库(在线、毫秒级查询)、温库(在线但少查,可放低成本存储)、冷库(离线归档,接受分钟级查询或查原始文件)。分层越细,成本优化空间越大,但管理复杂度也越高,小团队先做热冷两档就够了。
-- 查看各表数据量与最后访问时间,确定冷热
SELECT table_name, table_rows,
UPDATE_TIME, CREATE_TIME
FROM information_schema.tables
WHERE table_schema = 'appdb';
归档表与分区表设计
归档区可以放在原库的归档表,也可以放到独立库甚至独立存储。设计归档表时,字段结构与原表保持一致,但可以去掉只在热查询里用到的二级索引,减少写入成本;唯一约束要保留,防止重复归档。分区表是冷热分层的最佳搭档:按业务时间做 RANGE 分区,归档就是搬一个分区,而不是删百万行。
CREATE TABLE orders (
id BIGINT,
order_time DATETIME,
-- 其他业务字段省略
) PARTITION BY RANGE (YEAR(order_time) * 100 + MONTH(order_time)) (
PARTITION p202501 VALUES LESS THAN (202502),
PARTITION p202502 VALUES LESS THAN (202503),
PARTITION p202510 VALUES LESS THAN (202511)
);
分区表让查询自动裁剪:带分区键的查询只扫对应分区,不带分区键则全分区扫描,所以业务查询要尽量带上时间条件。归档时用 EXCHANGE PARTITION 把整个分区原子地换到归档表,秒级完成,不产生大量删除日志。
归档流程与定时任务
归档是个周期性动作,靠定时任务驱动。典型流程:任务扫描分区或按时间条件找过期数据;先把数据复制到归档表,确保归档区完整;再删除原表数据;最后记录归档日志,更新元数据。复制与删除之间要留窗口,防止业务查询读到正在搬移的数据。
-- 归档示意:插入归档表再删原表
INSERT INTO orders_archive
SELECT * FROM orders
WHERE order_time < DATE_SUB(NOW(), INTERVAL 90 DAY)
LIMIT 10000;
DELETE FROM orders
WHERE order_time < DATE_SUB(NOW(), INTERVAL 90 DAY)
LIMIT 10000;
- 分批小批量循环,避免长事务。
- 窗口错开业务高峰执行。
- 幂等重复执行不产生重复数据。
- 日志记录每批归档的条数与时间。
分区表的归档更简单:到期分区直接 EXCHANGE 出去,再把新分区挂进来。定时任务要加互斥锁,防止多实例同时跑把数据搬重了。
查询改造与数据生命周期
归档后,原来"一条 SQL 查全表"的写法要改造:历史查询走归档库或归档接口,近期查询走热库;对账类任务改为按时间分段并行跑,先热库后冷库再合并结果。应用层要感知数据分层,不能让用户感觉"查不到历史数据",常见做法是提供统一的查询入口,底层自动路由冷热。
// 查询路由示意:先热库,再归档库
result = queryHot("orders", conditions);
if (result.empty) {
result = queryArchive("orders_archive", conditions);
}
数据生命周期管理把归档纳入常态:定义每类数据的留存期限、归档时机与最终销毁策略;合规要求保留五年的,到期才能销毁;销毁要可审计、可验证,不能删完才发现还要用。生命周期表(数据类别、留存期限、归档目标、销毁时间)是治理的元数据基础。
归档后的校验与回滚
归档最大的风险是丢数据:复制不完整、删除删多了、任务重复跑出脏数据。因此归档后必须有校验环节:对比原表与归档表的总行数与关键字段总和,用计数与校验和双重确认;校验通过后才算归档完成,否则标记失败并告警。回滚预案也要备好:归档表保留一份,删除原表前可以先软删除(加标记位),确认无误后再物理清理。
-- 校验:行数与金额合计一致才归档完成
SELECT COUNT(*), SUM(amount) FROM orders_archive;
SELECT COUNT(*), SUM(amount) FROM orders;
真实项目里还常加一道"灰度归档":先归档一个月的数据跑通全流程,观察一周无异常再放开全量。归档任务出问题时,暂停任务、定位批次、从归档日志反推受影响范围,比急着删数据重要得多。
落地清单
- 用访问统计确定冷热边界,先做热冷两档分层。
- 时间型大表启用分区,按业务时间 RANGE 分区。
- 归档表结构与原表一致,去掉多余索引保留唯一约束。
- 定时任务分批执行、幂等、带互斥锁,错开业务高峰。
- 查询入口统一路由冷热,历史查询不落空。
- 归档后校验行数与校验和,保留回滚与销毁预案。