做 RAG 或者加个语义搜索,第一反应常是「上向量数据库」;可业务数据本来就在关系库里,于是纠结要不要再来一套。这篇不讲产品参数,只把两边的数据模型、查询语言、事务与索引差异摆清楚,再给一张按场景对照的判断表和接入前的检查清单,让你能自己拍板,也能说服同事。
做 RAG 或者给现有产品加个语义搜索,很多人的第一反应是「上向量数据库」。可业务数据本来就躺在关系库里,于是开始纠结:要不要再养一套组件、要不要把数据搬过去。这篇不聊产品参数,只把两边的数据模型、查询方式、一致性与运维差异摆清楚,再给一张按场景对照的判断表和接入前的检查清单,让你能自己拍板,也能在评审会上说服同事。
先记住一句话:两者不是替代关系,而是解决的问题不同。关系库解决的是「这条记录准不准、能不能按业务规则算清楚」;向量库解决的是「哪几条跟我这句话最像」。把这两个问题混在一起想,选型就永远定不下来。
数据模型:一行记录 vs 一个向量
关系库存的是结构化行与列,每个字段有明确类型、长度和约束,表与表之间用主键外键串起来,数据本身是自洽的。向量库存的核心是一串高维浮点数,再加一份元数据(payload),语义全部压在这串数字里——它不知道这串数字代表什么,只知道两条数字之间离得近不近。
- 主键与外键
- 关系库靠约束保证引用完整,向量库通常只保证「按 id 找得到某条向量」
- 元数据过滤
- 向量库的 payload 能按字段筛,但字段类型和索引能力一般弱于关系库的业务表
- 语义载体
- 关系库的语义在字段名、枚举值和注释里;向量库的语义在向量本身,人类不可读
- Schema 变更
- 关系库改字段要走迁移;向量库改维度基本等于重建整个索引
判断标准很简单:如果你的核心动作里出现 JOIN、聚合、事务、唯一约束,重点在关系库;如果核心动作是「给一段输入,找出最像的几条」,重点在向量库。两者都需要时,别急着二选一,往下看搭配方式。
- 需要跨表统计、对账、生成报表:关系库,且不要指望向量库补位
- 需要按复杂条件分页、排序、做权限隔离:关系库
- 需要模糊语义匹配、跨语言检索、以图搜图:向量库
- 两类需求都有:关系库做唯一事实来源,向量库存 id + 向量
查询方式:SQL 精确匹配 vs 近似最近邻
关系库写 SQL,条件写死多少就返回多少,结果是确定的集合,同一句 SQL 跑十遍结果一致,天然可解释、可复现。向量库做的是近似最近邻检索,返回「距离最近的 N 条」,同一份数据换一次索引参数或者索引重建方式,召回结果就可能变——这不是 bug,是这类索引的设计取舍。
更麻烦的是相似度阈值、Top-K 和过滤条件三者会相互影响。过滤条件写得太严,召回会被压得没几条;放得太松,真正相关的结果又会被淹掉。所以向量检索的结果建议做二次校验:先召回一批,再用关键词、规则或一个更小的模型重排。别把它当成精确查询来用,也别用「查不到就是没数据」去质疑它。想搞清两者在原理层面的差别,可以先到 /stacks/vector-dbs 看目录页面的分类说明。
| 对比项 | 关系数据库 | 向量数据库 |
|---|---|---|
| 查询写法 | SQL,条件与结果一一对应 | 相似度检索,给 Top-K 与阈值 |
| 结果确定性 | 同条件结果稳定复现 | 受索引参数影响,可能变化 |
| 解释性 | 条件即原因,好排查 | 排名靠分数,需重排辅助判断 |
| 典型误用 | 拿 LIKE 做语义匹配 | 拿向量检索当精确查询用 |
一致性与运维:事务边界和成本边界
关系库有成熟的事务、备份、恢复和回滚流程,这是它几十年积累下来的最大优势。向量库的写入通常是最终一致,删除和更新还要考虑索引重建的时间差——你删掉一条记录,索引里可能还残留一段时间,检索时仍可能被召回。
成本这块别拍脑袋。向量库的内存和存储开销大致随「向量条数 × 维度」上涨,扩容前先把数据量算清楚,别按文本条数或文档篇数估算。至于具体的内存占用、吞吐和单价,各家中转与云厂商差异很大,到 /price-watch 核对当时的数字再决定容量。
- 先定唯一事实来源明确业务库是唯一事实来源,向量只作为可重建的派生数据;重建一次不该丢任何业务信息
- 写入顺序固定下来业务写库成功后再触发向量生成,用任务队列补跑失败项,不要反过来先写向量
- 给向量打版本号每条向量带上源记录版本号,检索回来时和当前记录比对,版本不一致就丢弃或重新生成
- 准备重建方案估算全量重建一次要多久,把这套流程脚本化,避免索引损坏时手忙脚乱
- 上线前压测召回用一批真实查询跑召回率和延迟,参数一旦调整,重跑同一批用例做对比
两边混用时最常见的坑是双写不一致:文档更新了业务库,向量却没重新生成,检索就会返回过时甚至已删除的内容。上面这套顺序和版本号机制,基本能挡住大部分这类问题。
什么情况下不该硬换,而是搭配用
数据量小、语义需求弱的时候,直接在关系库里加全文索引就够了,多引一套组件只是多一份运维负担和故障面。反过来,需要强事务又需要语义搜索时,常见做法是关系库做事实来源,向量库只存 id 和向量,检索出 id 后回表取全量字段——这样字段变更、权限过滤、统计聚合都还在熟悉的关系库里。
- 纯离线、更新极少的知识库:可以把向量落成文件,用现成的向量扩展加载,省掉一套常驻服务
- 高并发写入场景:写入压力交给关系库或消息队列,向量生成异步做
- 跨租户强隔离需求:隔离逻辑放在关系库侧,向量库按租户分库或按前缀过滤
- 需要按复杂条件分页统计:这类需求交给关系库,向量库只负责召回那一跳
不适用的情况也要说清楚:如果你的业务对延迟极其敏感、又要求检索结果完全确定可复现,那向量检索本身就不该放在主链路上,更适合做离线的候选生成;如果团队里没人愿意长期维护索引重建和参数调优,引入向量库大概率会变成一个没人敢动的黑盒。
| 你的场景特征 | 建议选型 | 理由 |
|---|---|---|
| 数据量小、只需关键词匹配 | 关系库全文索引 | 组件少,查询可解释 |
| 既要事务又要语义搜索 | 关系库 + 向量库(存 id) | 事实与召回各归其位 |
| 更新极少、离线可用 | 文件式向量索引 | 省服务,部署简单 |
| 高并发写入 + 复杂权限 | 关系库为主,向量异步 | 一致性靠主库兜住 |
| 结果必须完全可复现 | 不要放主链路 | 近似检索天然有波动 |
接入前建议再过一遍检查清单:向量维度是否锁定、重建脚本是否可跑、召回结果是否有重排、写入失败是否有补偿、容量估算依据是否来自实际压测。这几项都答得上来,再决定引入哪家服务也不迟。
下一步选型定下来之前,先去看各家向量库和中转服务的实测表现与可信度记录,站内已经整理好了对比维度,比盲目试跑省时间。→常见问题
我数据量不大,能不能只用关系数据库做语义搜索?
可以。很多关系库已经支持向量列或者扩展,条数在上万级别、查询并发也不高时,直接在原库里做就够了,省掉一套服务。判断点在于:数据要不要经常全量重建、查询延迟要求多严、并发峰值多高。一旦重建耗时开始影响发布节奏,或者并发把主库拖慢,再拆出去。具体产品能力去站内向量数据库目录核对当时的支持情况。
向量库和关系库的数据要怎么保持一致?
推荐单向以关系库为准:业务写入成功后发一条任务,重新生成该记录的向量并覆盖旧向量;向量里存源记录 id 和版本号,检索回来先按 id 回表校验版本,版本对不上就丢弃或重取。删除同样走这个链路。不要两边各自写,也不要在应用层做双写事务,中间断了很难查。
选型的时候最该先确认哪几件事?
先确认四件:数据条数与向量维度、更新频率、延迟要求、是否需要按字段做复杂过滤。这四点定了,方案基本就只剩一两种。之后再去看具体产品的索引类型、过滤能力与部署形态,站内的向量数据库目录里能按这些维度横向比。价格和额度这类会变的数字,直接到相关页面看当时的值。