我们在 RAG 项目上换过三次向量库。这篇把三次踩的坑写清楚,让后面的人别重走。
可复现前提: 数据集为内部文档 120 万段(脱敏后开放在 datasets/docs-1.2m),硬件为 8C32G 单机。你的数据量差一个数量级,结论可能就不一样——请自己跑一遍再下结论。
教训一:先量数据,再选库
我们最开始按"社区最热"选了一个库,上线三周后数据量涨到 80 万段,单机内存直接吃满。选型前应该先估算 12 个月后的规模,而不是当前规模。
我现在的估算方式很土但够用:
# 当前文档总字数 / 平均切片长度 * 预期年增长
echo $(( 4_200_000 / 400 * 3 ))教训二:召回率要在自己的数据上测
公开 benchmark 上排名靠前的,在我们的中文技术文档上表现平平。三个库在同一份 200 条人工标注问答上的 recall@5:
| 向量库 | recall@5 | P95 延迟 | 单机内存 |
|---|---|---|---|
| A | 0.71 | 42ms | 26GB |
| B | 0.83 | 88ms | 11GB |
| C | 0.81 | 31ms | 18GB |
最终选了 B:召回率高出 12 个百分点,88ms 的延迟在我们的场景里完全可接受。
教训三:运维成本是隐性大头
A 库性能不错,但它的备份恢复流程需要停服。我们真的因为这个在一次故障里多停了 40 分钟。能不能热备、能不能滚动升级,这两个问题要在选型时就问。
教训四:别低估重建索引的时间
换库要重建全量索引。120 万段第一次重建花了 9 小时,期间新写入的数据全丢了——因为我没做双写。第二次换库时的正确做法:
- 新库建好,开启双写
- 后台批量回填历史数据
- 影子流量对比两边召回结果,连续 3 天差异 < 2% 才切
- 切读流量,老库保留两周再下线
教训五:元数据过滤的性能差异极大
我们需要按部门、时间范围过滤。三个库里有一个是"先向量检索再过滤",数据倾斜时会出现召回不足——检索回来的 100 条里可能一条都不属于目标部门。要选支持预过滤的库,这一条差点让我们上线后返工。
决策表
| 你的情况 | 建议 |
|---|---|
| < 10 万段,快速验证 | 用内存库,别上服务 |
| 10 万 ~ 200 万段,单机 | B 类库,注意预过滤支持 |
| > 500 万段或多租户 | 上托管服务,自建运维不划算 |
| 强过滤需求 | 只考虑支持预过滤的 |
评论与复现反馈 2
教训四的双写方案我们照做了,120 万段回填花了 6 小时,影子对比跑了 4 天才敢切。建议把「保留两周再下线」也写成硬规定。
想确认下,「预过滤」是指在向量检索之前就按元数据筛掉候选集吗?这个能力在选型时怎么快速验证?