为什么 RAG 要用向量数据库?其他数据库不行吗?
结论:不是"必须用向量数据库",而是"必须解决高维最近邻检索"。B+ 树擅长一维有序查找,倒排索引擅长词面命中, 两者都无法回答"哪段文本和我这句话意思最接近"。数据量小的时候,PostgreSQL 加个 pgvector 扩展、甚至内存里暴力点积,都算合格的方案。
1. 问题本质:在 1536 维空间里找最近的点
一维(B+ 树的主场)
1.2 3.5 7.0 9.9 ← 有序,二分即可定位,范围查询天然支持
高维(B+ 树失效)
A(0.11, -0.42, 0.87, ...) 1536 个分量
B(0.13, -0.40, 0.85, ...) 与 A 距离 0.03
C(-0.9, 0.31, 0.02, ...) 与 A 距离 1.72
—— 没有哪个分量能单独代表"离 A 近",索引无从剪枝
精确求解要遍历全表,复杂度 O(N·d)。百万级片段乘上 1536 维,单次请求就是几十亿次浮点运算,延迟不可接受。
所以工程上用近似最近邻(Approximate Nearest Neighbor,ANN):牺牲 1%5% 的召回率,换 23 个数量级的速度。
2. 四类索引的能力对比
| 结构 | 剪枝依据 | 擅长 | 在高维向量上的短板 |
|---|---|---|---|
| B+ 树 | 一维全序,区间可二分 | 主键、时间、金额 | 距离无全序,无法二段式剪枝 |
| 倒排索引(Inverted Index,BM25) | 词项 → 文档列表 | 型号、错误码、人名精确命中 | 同义词、口语改写、跨语言全丢 |
| 图索引(HNSW) | 分层可导航小世界图 | 低延迟、高召回 | 内存占用大,删改代价高 |
| 聚类索引(IVF,倒排文件) | 先聚类再桶内扫描 | 亿级数据、内存可控 | nprobe 小了漏召回,大了退化成全扫 |
HNSW(Hierarchical Navigable Small World)之所以成为默认选项:查询是沿着图"贪心下降",平均复杂度接近 O(log N), 不需要训练,增量插入友好;代价是每个向量要维护 M 条邻居边,内存通常是原始向量的 1.5~2 倍。
3. 上代码:用 PostgreSQL 直接做向量检索
-- 已有 PG 的团队最省事的路径:不引入新的存储组件
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE doc_chunk (
id bigserial PRIMARY KEY,
source text NOT NULL,
content text NOT NULL,
embedding vector(1536) NOT NULL -- 维度必须与 embedding 模型一致
);
-- HNSW:查询快、构建慢、吃内存,适合在线低延迟
CREATE INDEX idx_chunk_hnsw ON doc_chunk
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
SET hnsw.ef_search = 40; -- 运行时旋钮:越大召回越高、越慢
SELECT id, source, content,
1 - (embedding <=> $1) AS score -- <=> 余弦距离,<-> 欧氏,<#> 负内积
FROM doc_chunk
WHERE source = 'employee-handbook' -- 元数据过滤
ORDER BY embedding <=> $1
LIMIT 20;
过滤条件和 ANN 索引一起用时要注意:先过滤再走图,可能因为候选集太小而"走进死胡同",返回条数不足; 先走图再过滤,又可能过滤掉大半。主流实现会给这两种策略做自适应,遇到返回不足的情况再看版本是否支持迭代扫描。
4. 什么时候根本不需要向量数据库
| 场景 | 够用的方案 |
|---|---|
| 片段 < 10 万,单机 | numpy 矩阵乘法暴力算,几十毫秒 |
| 已有 PostgreSQL | pgvector,运维零新增 |
| 查询以型号/编号为主 | Elasticsearch 的 BM25 就够 |
| 要同时支持语义和关键词 | 向量库 + 倒排,做混合检索 |
5. 常见追问
Q:向量库能替代 Elasticsearch 吗? 不能。日志检索、聚合统计、精确过滤仍是 ES 的主场;现在多数团队是"ES 做召回一路,向量库做另一路"。
Q:为什么 ANN 是近似的? 图索引只保证"大概率"走到真近邻里,出口条件(ef_search、nprobe)决定探索广度。生产上要自己算 recall@10:抽 200 条查询,用暴力解当标准答案对比。
Q:100 万条 1536 维向量占多少内存? 原始向量约 1536×4 B ≈ 6 KB/条,合计约 6 GB;加上 HNSW 的图结构,通常按 10~15 GB 预留。这也是量化(PQ、int8)存在的原因。
Q:删文档会影响索引吗? HNSW 的删除是标记删除,图结构不会立刻重排,长期增删后需要重建索引来恢复召回。
小结
选型的判断顺序是:数据规模 → 过滤复杂度 → 运维成本。别为了"架构好看"给一个十万条的知识库上分布式向量集群。