朋友圈存储从 600G 收口到 3G:位图与事件模型改造记录
简单记录一次朋友圈存储治理:将原本约 600G 的明细模型切换为约 3G 的位图/事件模型,在保持业务结果一致的前提下,完成旧表停写、历史迁移和旧表清理。
下文表名、字段名均为示意代称,不对应线上真实命名。
问题现象
早期的朋友圈可见范围和互动数据,主要通过两张明细表保存:
t_visible_snapshot_v1(发布前可见明细)t_visible_snapshot_v2(发布后可见明细)
随着朋友圈数量和客户数量增长,旧模型逐渐暴露出几个问题:
- 客户关系逐行存储,数据量持续膨胀。
- 发布前 / 发布后两套明细存在大量重复。
- 索引维护、WAL、vacuum 和备份成本不断增加。
- 读写链路长期维护 old/new 两套模型,查询和排障复杂。
问题的本质不是 SQL 不够快,而是用明细行表达集合的成本太高。
新模型设计
1. 可见关系改为位图
新模型使用 t_visible_bitmap 保存可见关系,核心字段可理解为:
bitmap_before:创建时可见客户集合bitmap_pending:发布后仍未触达的客户集合
触达客户集合通过差集计算:
touched = bitmap_before - bitmap_pending
这样无需在“发布后明细表”中重复保存完整客户明细。
2. 点赞、评论改为事件表
点赞和评论统一写入 t_interact_event,独立保存朋友圈、客户、互动类型和互动时间。
新旧模型对比如下:
| 对比项 | 旧模型 | 新模型 |
|---|---|---|
| 可见关系 | 客户明细逐行存储 | 位图集合 |
| 未触达关系 | 独立明细记录 | 差集位图 |
| 点赞/评论 | 附着在明细记录上 | 独立事件表 |
| 写入链路 | old/new 双写 | 只写新模型 |
| 查询链路 | 两套明细表 | bitmap + event |
改造过程
本次按“先切读、再切写、后清理”的顺序推进:
- 将页面、接口、报表查询切换到位图和事件模型。
- 停止旧表双写,分别写入位图快照、差集位图和互动事件。
- 分批把历史明细转换为位图和事件,按批次记录进度并校验结果。
- 确认代码、配置、数据库对象和运行日志不再依赖旧表后,删除旧表索引及表本体。
结果验证
存储空间
| 对象 | 改造前 | 改造后 |
|---|---|---|
| 朋友圈旧明细模型 | 约 600G | - |
| 可见位图表 | - | 约 2.6G |
| 互动事件表 | - | 约 32MB |
| 新模型合计 | - | 约 3G |
业务主承载空间由约 600G 收口到约 3G,减少约 597G。旧索引清理阶段先释放约 300G,旧表清理后完成剩余空间回收。
业务一致性
抽样验证了以下结果:
- 创建时可见客户集合一致。
- 发布后未触达客户集合一致。
- 已触达、未触达统计口径一致。
- 点赞、评论数量和互动时间保持可查询。
因此,这次改造不是简单删除历史数据,而是用新的数据模型无损替代旧模型。
总结
朋友圈这次优化的关键,不是清理了多少行数据,而是改变了数据表达方式:
明细行集合 -> 位图集合
重复明细 -> 差集计算
互动附着 -> 独立事件
当大表已经进入数百 GB 规模时,继续加索引、调 SQL 往往只能缓解局部问题。让存储结构与业务语义匹配,才是实现 600G -> 3G 收口的核心。