28 · 数据库与存储选型
一句话点题:数据库不是「MySQL 还是 PostgreSQL」这么小的问题,而是「这份数据的读写模式、一致性要求、查询形态、增长速度和失败代价是什么」。选存储,先画数据生命周期;工具名排在后面。
🧰 技术栈选型篇第 2 章 · 本章只练一件事
05 章 说过:系统真正难的不是逻辑,是数据。语言可以换,服务可以拆,但数据一旦放错地方,迁移成本会非常高。本章把数据库、缓存、搜索、对象存储、向量库放到同一张选型地图里看。
开场:别用一个数据库扛所有问题
很多系统一开始长这样:
App ──▶ 一个关系型数据库
├─ 交易数据
├─ 报表查询
├─ 搜索筛选
├─ 文件附件
└─ AI 检索向量MVP 这样做没错。问题是,随着业务长大,这些数据的访问方式完全不同:
- 订单要强一致,不能丢。
- 报表要扫大量历史数据,不能拖垮主库。
- 搜索要相关性排序,不是简单
LIKE。 - 图片、视频、附件要便宜存、能走 CDN(内容分发网络)。
- RAG(检索增强生成)要向量召回和权限过滤。
**架构判断:**不是「哪个数据库最好」,而是「哪类数据,该用哪种存储模型承载」。一个系统常常需要多种存储,但每增加一种,都会增加一致性、同步、运维和排障成本。
一、先画数据生命周期
选数据库之前,先把一类数据从出生到归档画出来:
写入 ──▶ 校验 ──▶ 事务提交 ──▶ 查询/检索 ──▶ 分析/报表 ──▶ 归档/删除
│ │ │ │ │ │
谁写? 怎么验? 要多一致? 怎么查? 多久查一次? 保留多久?然后回答五个问题:
| 问题 | 为什么重要 |
|---|---|
| 写多还是读多? | 决定是否需要读写分离、缓存、索引模型 |
| 事务边界在哪里? | 决定能不能用关系型数据库的事务兜住 |
| 查询形态是什么? | 主键查、范围查、全文搜索、向量相似度,完全不同 |
| 数据增长速度多快? | 决定分区、冷热分层、归档策略 |
| 错了会怎样? | 决定一致性、备份、审计、恢复等级 |
这一步和 07 章 的信封背面估算是一回事:先算数据量、读写比、保留周期,再谈工具。
二、主存储:关系型数据库仍然是默认起点
如果你不知道该选什么,大多数业务系统默认从关系型数据库开始:
| 类型 | 适合 | 不适合 |
|---|---|---|
| 关系型数据库(如 PostgreSQL、MySQL) | 交易、订单、权限、租户、账务、需要事务的数据 | 极大规模分析、全文搜索、海量非结构化文件 |
| 文档数据库(Document DB,如 MongoDB) | 结构经常变化、文档整体读写、弱关系数据 | 强事务、多表复杂关联、严格报表 |
| 键值存储(Key-Value,如 DynamoDB、Redis 持久化形态) | 按 key 高速读写、结构简单、超大规模 | 临时复杂查询、灵活关联 |
| 列式/分析数据库(OLAP,在线分析处理) | 报表、聚合、日志分析、行为分析 | 高频小事务写入 |
**默认建议:**先用关系型数据库把核心交易数据放稳。等报表、搜索、日志、向量检索真的变成独立压力,再把对应读模型拆出去。不要一上来为了「现代」把每类数据都塞进不同数据库。
三、读模型:搜索、分析、向量不是主库的附属品
当查询形态开始偏离主库擅长的方向,就要考虑读模型:
| 需求 | 常见存储/引擎 | 关键取舍 |
|---|---|---|
| 全文搜索 | Elasticsearch、OpenSearch、Meilisearch | 相关性强,但索引同步和最终一致要处理 |
| 报表分析 | ClickHouse、BigQuery、Snowflake | 扫描聚合快,但不是交易主库 |
| 对象存储 | S3、OSS、GCS | 存文件便宜可靠,但不能当数据库做复杂查询 |
| 向量数据库(Vector DB) | Milvus、Qdrant、pgvector | 相似度检索强,但权限过滤、召回质量和成本要评估 |
| 时序数据库(Time Series DB) | Prometheus、InfluxDB | 指标时间线查询强,但不适合普通业务对象 |
这里最容易犯的错是把读模型当成事实源:
正确:
主库 = 事实源(Source of Truth)
搜索/分析/向量库 = 从主库或对象存储同步出来的读模型
错误:
用户改了资料 → 只改搜索索引 → 主库不知道读模型可以落后,但要说清楚能落后多久、怎么补偿、怎么重建。这就是 11 章 的一致性工程。
四、RAG 场景:向量库不是唯一答案
RAG 企业知识库(案例 03 DocuMind)很容易被简化成:
文档切块 ──▶ 向量库 ──▶ topK ──▶ LLM 回答真实系统更像:
原文对象存储 ──▶ 解析/切块 ──▶ 元数据主库
│ │
├────────▶ 关键词索引 ◀────┤
├────────▶ 向量索引 ◀────┤
└────────▶ 权限/租户过滤 ◀──┘选型时要问:
- 权限过滤是在检索前做,还是检索后过滤?后过滤可能召回不够。
- 只做向量召回,还是混合检索(Hybrid Search,关键词 + 向量)?
- 原文和引用存在哪里?向量库不应该是唯一事实源。
- 索引坏了能不能从原文和元数据重建?
- 成本能不能随文档量和查询量线性增长?
向量库解决的是「相似度召回」,不是权限、事实源、引用、评测的全部问题。不要把一个 RAG 系统压扁成一个库。
五、什么时候该拆存储
拆存储的触发信号要具体:
| 信号 | 说明 | 可能动作 |
|---|---|---|
| 报表查询拖慢交易库 | OLTP(在线事务处理)和 OLAP(在线分析处理)互相干扰 | 同步到分析库 |
| 搜索相关性差、LIKE 扫描慢 | 查询形态变成全文搜索 | 建搜索索引 |
| 附件/图片撑爆数据库 | 二进制文件不该塞主库 | 迁到对象存储 + CDN |
| 单表增长导致索引和备份变慢 | 数据生命周期没有分层 | 分区、归档、冷热分离 |
| RAG 召回质量不稳 | 单一向量召回不够 | 混合检索 + 重排 + eval |
也要记住反面:
如果当前数据量小、团队少、故障代价低,一套关系型数据库 + 合理索引 + 定期备份,往往比过早引入五种存储更健康。
六、写一条存储选型 ADR
### ADR-028:报表查询从交易库拆到 ClickHouse
- 背景:工单列表和状态流转依赖主库,但月度报表开始扫描 2 亿行历史事件,导致交易库 P99 从 120ms 升到 900ms。
- 选择:主库继续作为事实源;通过 Outbox 事件同步到 ClickHouse,报表只查分析库。
- 放弃:放弃报表的强实时性,允许 1 分钟以内延迟。
- 换来:交易链路与报表链路隔离,报表聚合性能提升,主库负载稳定。
- 复审条件:如果报表必须秒级实时,或同步延迟超过业务可接受范围,重新评估流式同步和预聚合。这条 ADR 的关键是:它没有说「ClickHouse 很快」,而是说清楚了哪个读模型拖垮了哪个事实源。
🎯 随堂检验
- A关系型数据库,用事务、约束和状态机守住核心交易数据
- B全文搜索引擎,因为查询很灵活
- C对象存储,因为便宜
- A它们都应该各自成为事实源,这样最灵活
- B主库或原始对象存储通常是事实源,搜索/分析/向量库是为特定查询形态同步出来的读模型
- C只要用了向量库,就不需要元数据和权限库了
本章小结
- 选存储先画数据生命周期:写入、校验、事务、查询、分析、归档,每一步都有约束。
- 关系型数据库仍是多数业务系统的默认事实源:先稳住核心交易数据,再拆读模型。
- 搜索、分析、向量库是不同查询形态的读模型:它们强在特定查询,弱在事务和事实源。
- RAG 不是一个向量库:还包括原文、元数据、权限、混合检索、重排、引用和 eval。
- 拆存储要靠触发信号:报表拖垮主库、搜索变慢、附件撑爆库、召回质量不稳,这些才是升级理由。
承上启下:主存储解决「事实放在哪里」。但系统一旦有热点、洪峰、异步协作,就会遇到缓存、消息队列和事件系统。下一章 29 · 缓存、消息队列与事件系统选型,我们专门讲这些「很有用,也很容易被误用」的中间层。
相关链接
- 方法论本体:05 · 数据与状态 · 06 · 质量属性与取舍 · 11 · 数据一致性工程
- 演进配套:13 · 规模化的力学 · 14 · 演进与拆分大型系统
- 案例对照:DocuMind:企业 RAG 知识库 · StarArena:演唱会抢票系统
💬 评论