清算系统产生的数据有个尴尬的属性:写入一次、读取两次,然后躺十年。第一次读取是日终对账,第二次可能是三年后的监管调取。监管对账务数据的保存年限要求普遍在十年以上,意味着任何一家券商都要回答同一个问题:怎么让十年前的流水"可查"又不让十年的数据把生产系统拖死。这篇讲这个成本账怎么算、归档架构怎么落。
访问频率决定存储层级
归档设计的第一性原理很简单:存储成本应该和访问频率匹配。生产数据的存储贵(高可用、低延迟、带备份),但十年前数据的访问频率可能是一年一两次——给它生产级的待遇就是浪费。按访问频率把数据切成三层:
- 热层(近 3~6 个月):生产库。高频访问——对账、查客户流水、风控统计都在这层。保留策略的驱动因素是业务而非监管:客户打电话来查上个月的交割单,这个查询必须秒回。
- 温层(约 1~3 年):历史库。访问频率骤降,但审计、司法调取、客户历史对账还时不时来。这一层可以牺牲一点延迟换成本:独立的只读实例、更低的 IO 规格。
- 冷层(3 年以上到监管年限):归档存储。列式压缩格式或对象存储,单次查询分钟级甚至小时级可接受——监管调取走的是正式流程,本来就有时间余量。
分层之间是单向迁移:数据只从热往冷搬,不回头。迁移动作本身是批量任务,纳入清算的日终调度——每天把超过热层窗口的分区迁往温层,按季度或年度把温层的旧数据打包进冷层。注意迁移窗口的选择:账务数据当日还有被对账和追账引用的可能,迁移时机必须在对账闸门之后、且当天的修复流程关闭之后。
分区是按交易日的,不是按自然月的
账务数据的天然分区键是交易日,不是自然月也不是录入日期。所有清算流水、持仓快照都带交易日期字段,按它范围分区,归档动作就是"detach 整个分区、搬到目标层"。这个设计的收益有三层:
- 归档是元数据操作不是数据搬运:分区表的 detach 只改目录,不搬数据行。TB 级的历史分区归档可以在秒级完成,之后数据文件再用后台任务异步拷贝到归档层。
- 查询自动带裁剪:按交易日查历史("把 2022 年 3 月全部对账差异调出来")只扫描命中分区,不会因为分区策略错误扫全表。
- 删除也有边界:监管年限到期后的数据销毁,按分区整批处理,精确且可审计。
反面教材是按账户哈希分区存历史数据——那是为并发写入设计的分区键,对历史归档毫无帮助,还会让"某一天的全量数据"散落在全部分区上,归档和查询都退化成全表操作。
成本账:行存、列存、压缩、对象存储
把十年的流水数据量级估出来才有讨论成本的基础。一个中等规模券商,日终清算生成全量流水约百万行、占用几 GB;十年 2500 个交易日,累计约几十亿行、十几 TB——还在单机数据库能扛的范围内,但已经不便宜了。四个降本手段的账本:
| 手段 | 压缩比量级 | 查询能力 | 适用层 |
|---|---|---|---|
| 行存 + 页压缩 | 2~3 倍 | 全功能 SQL | 热层 |
| 列存格式 | 5~10 倍 | 分析型查询快、点查弱 | 温层 |
| 归档压缩包 | 10 倍以上 | 需解包恢复 | 冷层 |
| 对象存储 | 同归档 | 分钟级取回 | 冷层 |
冷层还有一个选择是磁带库或离线介质,监管数据的离线保存要求使得很多机构保留这一手。但"离线"和"可查"是矛盾的,实际做法通常是在线归档(对象存储)为主、离线介质为合规备份,两边保留同样的数据。
历史库的第一铁律:不许影响生产
温冷层的所有查询都有一个共同风险:一条写砸了的 SQL(忘带分区条件的全表扫描)在生产库跑是事故,在历史库跑只是慢——但历史库和生产库共享的东西如果太多,事故照样传导。三条隔离原则:
- 物理隔离:历史库是独立实例,不是生产库的只读副本挂在同一存储上。副本共享存储,历史查询的大 IO 会直接挤占生产的 IO 预算。
- 资源隔离:历史库的查询账户有独立的资源限额(连接数、CPU 配额),超限直接排队或拒绝,宁可让历史查询失败也不反压。
- 入口隔离:历史查询走单独的查询网关,有审批流和审计日志。监管调取和内部排查都要留痕——调取了什么数据、谁批的、用于什么。这条不是性能要求,是合规要求,但落地时和性能隔离用的是同一套网关。
最后一个常被忽略的点:归档数据本身也要对账。数据从热层迁到温层再迁到冷层,每一跳都要校验行数、金额合计不变——搬迁任务生成源端和目标端的校验和(行数 + 金额 SUM + 哈希),不一致就报警回滚。账务数据在迁移中丢一行,十年后需要它的时候没有任何对账机制能发现,这比存储成本贵得多。