交易系统数据归档与在线查询的性能平衡,核心解法是冷热分层存储、预聚合索引与查询路由的协同设计把高频热数据留在高性能介质,将低频冷数据压缩归档到低成本存储,同时通过统一查询层让应用无感访问。
为什么交易系统的数据归档与查询总是互相打架
很多团队在交易系统上线初期,都经历过一段“数据随便查”的痛快日子,但随着运行时间拉长,数据库里的历史订单、行情快照、风控流水越堆越多,查询响应开始变得迟钝,这时候就会有人提出:把老数据挪走,归档到廉价存储里,但归档方案上线后,新的问题马上浮现:业务同事反馈有些历史报表查不出来了,或者要等好几秒才能看到结果。
这背后的矛盾其实很清晰:在线查询需要索引完整、随机读性能强,而数据归档追求压缩率高、存储成本低,两者在存储引擎、索引策略、硬件选型上天然对立,要想同时兼顾,不能靠单点优化,得从数据分层、生命周期管理、查询路由三个维度同时发力。
归档的本质不是把数据扔进冷宫
许多团队对归档的理解是“删完挪走”,这是认知误区,归档必须保留数据的可追溯性与可查询性,只是允许查询延迟略高、并发能力略低,业内专家指出,成熟的交易系统数据管理方案,通常把数据按访问频度分为热、温、冷三个层级,而不是简单的一刀切。
- 热数据:最近7天到30天内的订单、成交、实时风控记录,要求毫秒级响应,通常放在SSD或内存数据库中。
- 温数据:近1年的历史行情、结算明细,接受亚秒级到秒级查询延迟,可以存放在NVMe磁盘或高密度HDD上,配合列式存储压缩。
- 冷数据:超过1年的监管报送、审计日志、历史快照,查询频率极低,但必须保留且可检索,适合放入对象存储或成本更低的磁带/蓝光介质。
在线查询性能不能被归档拖累的硬性前提
在做归档设计时,有两条红线不能破:一是热数据区的查询性能不能因为归档任务产生明显抖动;二是跨层查询的SQL语义必须保持一致,应用层不能因为数据被归档而改写代码,这两条如果做不到,再低的存储成本都是虚的。
架构设计:给交易数据一个“三级存储接力赛”
热数据层:用内存加SSD撑住高并发
在交易系统里,当日订单和最新行情是并发访问最集中的区域,这一层通常采用Redis或内存网格缓存最近15分钟的热点数据,底层用MySQL或PostgreSQL承接最近7天的完整数据,配合SSD RAID阵列保证随机读性能,归档动作只发生在数据超过7天之后,完全不影响当前的交易写路径。
关键点:热数据层只保留在线交易必需的最小字段集,比如订单号、证券代码、买卖方向、价格、数量、状态,至于风控模型的中间计算因子、策略快照等字段,直接从第一天就进入温数据层。
温数据层:列式存储加分区索引解决范围查询

数据显示,交易系统的历史查询中,绝大多数是带时间范围的聚合统计,某客户过去三个月的成交总额”或“某支股票月线走势”,这类场景用行式存储会很吃亏,因为即使只查一个字段,也必须读取整行记录。
温数据层建议采用ClickHouse或Doris这类列式数据库,按日期做分区,每个分区内部按证券代码做二级索引排序,以某期货公司为例,其交易系统原本在Oracle里存放两年数据,查询“单个客户一年的交易笔数”需要6秒,迁移到列式存储后同一查询降到200毫秒,数据压缩比达到8:1,这已是行业共识的效率提升思路。
冷数据层:对象存储加透明归档网关
超过一年的数据,用Parquet或ORC格式压缩后放入MinIO或AWS S3,配合Hive或Trino做联邦查询,为了让应用层无感知,需要在数据访问层加一个透明归档网关应用发起查询时,网关先判断数据跨度,如果命中温数据层就直接查询;如果涉及冷数据层,就自动改写查询计划,从对象存储中拉取相应分区。
如何设定归档策略与查询路由规则
第一步:按业务属性划分数据生命周期
不同业务数据对查询时效性要求差异显著,不应使用统一的归档周期。
| 数据类型 | 热数据保留期 | 温数据保留期 | 冷数据保留期 |
|---|---|---|---|
| 订单/成交 | 7天 | 1年 | 5-10年 |
| 行情快照(tick级) | 1天 | 6个月 | 2年 |
| 风控流水 | 7天 | 6个月 | 3年 |
| 对账/结算文件 | 30天 | 2年 | 5年 |
第二步:归档任务调度避开交易高峰
归档任务本质是I/O密集型操作,切忌在交易时段执行,行业通行做法是设定在每日凌晨02:00到04:00之间启动批量归档任务,并且控制归档线程的带宽上限,避免磁盘队列深度过大反过来影响在线查询。
实操建议:在ClickHouse中,使用ALTER TABLE ... DETACH PARTITION将过期分区从主表分离,然后通过FREEZE导出到冷存储,整个操作是异步的,不会阻塞在线查询,分离后的分区需要维护一张归档清单表,记录分区对应的对象存储路径和日期范围,供查询网关做路由判断。
第三步:构建查询路由层,统一南北向接口
在应用层和存储层之间加一层查询路由服务(可用Java或Go开发),对外暴露统一的SQL查询接口,请求进来后,路由服务执行以下判定流程:
- 解析查询中的时间范围字段。
- 判断该时间范围落在哪些存储层。
- 如果跨层,将原查询拆分为两个子查询,并行下发到温数据层和冷数据层。
- 对冷数据子查询的结果追加标记字段
storage_tier = 'cold',对温数据层结果标记storage_tier = 'warm'。 - 合并结果集返回给应用,同时记录查询耗时与数据来源。

这套路由层最大的价值在于归档行为对业务侧完全透明,应用开发者不需要关心数据到底存在于哪一层。
归档后的在线查询性能调优细节
索引的“瘦身”与“增肥”要分开做
热数据存储层保留全部二级索引(用户ID、证券代码、订单状态等),因为在线查询条件多变,但温数据层的索引必须精简,优先保留时间字段和分区键,其他字段的索引一律去掉,这是因为列式存储中每个索引都会额外占用磁盘空间并拖慢写入速度,而温数据的访问模式相对固定。
预聚合技术让历史报表“秒开”
对于高频使用的监控报表,比如每日盈亏统计、成交额排名、持仓集中度,不需要实时扫原始明细,在归档任务执行的同时,可以生成日粒度、周粒度的预聚合结果表,存放在温数据层的独立小表中,查询端优先命中预聚合表,只有预聚合表不存在的维度组合才回源到明细数据。
这一招的效果非常直接原本需要扫描10亿行明细的查询,改为扫描1万行聚合结果,查询延迟从分钟级降至百毫秒级。
冷数据查询的等待时间要设阈值
冷数据从对象存储拉取到计算节点需要时间,不能让用户无限等待,建议在查询路由层设置冷数据查询的超时阈值,默认15秒,如果冷数据查询超过30秒未返回,网关直接切入异步模式先把查询任务加入队列,任务完成后将结果推送到用户预先注册的回调地址。
数据库归档后查询变慢怎么办
这是实践中最高频的问题,通常不是归档本身导致变慢,而是查询路由层没有正确处理查询计划。
排查路径:
- 先确认查询是否被路由到了预期层级,在路由管理后台查看该查询的
execution_plan字段,核对时间范围与数据所在分区是否匹配。 - 确认是否存在跨层数据重组,如果数据在归档前没有按相同排序键存储,跨层UNION后可能需要额外的排序或哈希操作,这一步往往最耗时。
- 检查冷数据层的文件大小与压缩率,对象存储中小于1MB的文件会大幅增加任务调度开销,定期执行
OPTIMIZE TABLE合并小文件,将单文件大小控制在64MB以上。
交易系统数据归档方案对比
不同规模的交易机构,选型侧重点差别很大。
小型量化私募(管理规模10亿以下):数据量大概在每年几百GB到几TB,没必要引入重型分布式组件,直接用MySQL的分区表加定时ARCHIVE存储过程,把历史分区转为ARCHIVE存储引擎即可,压缩率高查询速度可接受。
中型券商/期货公司(管理规模百亿级):每年产生几十TB数据,适合用ClickHouse做主仓库,配合MinIO做冷数据存储,中间用clickhouse-backup工具定时做分区备份,查询引擎直接连ClickHouse分布式表。
大型交易所/银行(管理规模千亿以上):需要湖仓一体架构,比如使用Iceberg或Hudi管理数据湖的表格式,底层存储在S3或HDFS,查询引擎用Trino或SparkSQL,这一层还要考虑跨地域容灾,冷数据副本至少保存两份,分布在不同的可用区。

性能验证:归档后你的系统到底行不行
上线归档方案后,不能凭感觉说“性能还行”,要有一套可量化的验证流程。
建立基线与压测模型
在归档方案实施之前,先记录一组基线数据:当前在线库中最近7天数据的平均查询耗时、P99毫秒值、慢SQL数量,实施归档后,再对以下三类场景做压测:
- 热数据查询:单笔订单查询、按用户查当日流水。
- 温数据查询:按月统计客户收益曲线、按产品类型查持仓汇总。
- 冷数据查询:查两年前的监管报送报表、拉取特定时段的tick级行情快照。
归档任务与在线查询的“碰撞测试”
专门构造一个场景:在归档任务正在执行的同时,向系统发起高并发查询请求,观察在线查询的P99允许延迟是否仍能保持在200毫秒以内,如果出现明显延迟,需要从资源隔离上找原因给归档任务设置iotop带宽限制,或者在存储层用cgroup隔离归档进程的CPU和内存使用量。
用成本账衡量归档策略是否合理
存储成本不只是磁盘价格,还包括备份空间、冷却能耗和运维人力。
据统计,行式存储的原始数据在采用列式压缩后,存储空间能降到原来的1/5到1/8,这意味着每年归档数据所需的物理机台数量可以直接砍半,这个数字来自多个头部云厂商公开的列式存储性能白皮书,具有一定的参考价值。
在成本评估时,建议按“每TB每年查询次数”来推算单位查询成本如果某些冷数据在归档后一年内只被查询过两次,就不值得为其配备高性能硬件,直接放到最低成本的存储层级即可。
常见问题
Q1:归档数据必须保留多久
取决于监管要求和内部审计策略,证券期货类交易数据需要留存至少20年,普通机构内部会设置5年、10年、20年三个阶梯,到期后经合规部门审批才可以销毁,具体存储周期建议咨询企业合规团队,确保归档时间线覆盖监管窗口期。
Q2:归档后原始数据文件还能被修改吗
不能,归档数据必须采用写一次读多次的不可变存储模式,任何补录或修正数据都应该以增量文件的形式写入新分区,而不是改动已有归档文件,一旦归档文件被篡改,整个审计链条就被破坏了。
Q3:ClickHouse和Doris做温数据层,哪个更适合交易系统
两者都能胜任高频聚合查询,ClickHouse在单表亿级数据量下的聚合性能更强,生态工具链成熟,适合按证券代码和时间范围做二维切片查询,Doris在联机事务和分析混合场景中的表现更均衡,如果你的交易系统本身有一些简单的事务更新需求,Doris的上手曲线更平滑,选型核心看你现有查询是以“跑报表”为主,还是“带条件的明细检索”为主,前者选ClickHouse,后者选Doris。