选向量数据库的时候,我被各种表格绕了很久。表格里十几种产品,列着"是否支持分布式""延迟多少毫秒",看完还是不知道该选哪个。
后来我换了思路:先算我的数据有多大。因为在大多数项目里,向量条数是唯一真正决定架构的变量。
先算内存,这是硬约束
一条 1536 维的 float32 向量占 6KB。这个数字很小,但乘上条数就不小了。
| 条数 | float32 裸向量 | 加上 HNSW 图结构 | 实际要准备的内存 |
|---|---|---|---|
| 10 万 | 0.6GB | +0.2GB | 2-4GB |
| 100 万 | 6GB | +2GB | 16GB |
| 1000 万 | 60GB | +20GB | 96-128GB |
| 5000 万 | 300GB | +100GB | 512GB 起步 |
HNSW 的图结构大概占裸向量的 30% 左右。真正吃内存的还有索引构建时的临时缓冲、查询时的邻接表、还有操作系统自己那部分。
所以我的第一个判断很简单:
所需内存 ≈ 条数 × 维度 × 4 字节 × 1.5
算出来的数字,跟机器上能分给向量库的部分比。放不下就别考虑了,这是唯一一条硬性红线。
分档:四档就够
第一档:10 万条以内——不要向量数据库
这个档位最容易被过度设计。我见过一个内部工具,8 万条文档,硬上了一套分布式向量库。
但 8 万条 1536 维的向量只有 500MB。一个 Python 进程里用 faiss 或者 hnswlib 建个索引,几秒钟的事,查询是微秒级,压根不需要网络往返。
这一档的正确做法是:进程内库,或者一个单文件的嵌入式方案。 没有服务、没有端口、没有额外机器。备份跟着主服务走。
反过来说,如果你发现自己在这档搭了独立服务,那不是"更专业",是凭空多出来的三个故障点。
第二档:10 万到 100 万条——一台机器内存里
这档开始有取舍了。
| 维度 | 进程内库 | 单机服务 |
|---|---|---|
| 查询延迟 | 最好,无网络 | 多 0.5-2ms 往返 |
| 多进程共享 | 麻烦,索引要么各建一份要么走共享内存 | 天然共享 |
| 独立扩缩容 | 不行 | 可以 |
| 运维成本 | 几乎为零 | 要管进程、端口、健康检查 |
我的分界线是:只有主应用在查就用进程内库;多个服务要查就起一个服务。 100 万条以内两者延迟几乎无可感差异——检索只要几毫秒,网络往返那 1ms 淹没在里面。
第三档:1000 万条以上——磁盘开始有意义
这一档开始,内存装不下了(960GB 显然不是大多数人能开的),必须考虑磁盘。
这时候真正的问题不是"用不用磁盘",而是怎么让磁盘不至于把延迟拖垮。
我试过几个方案:
- HNSW on-disk(hnswlib 的 mmap 模式):索引文件在磁盘上,靠 page cache 加速。查询是随机访问,冷缓存下 P99 能到几十毫秒,热缓存下回到毫秒级。
- IVF-PQ:倒排文件加乘积量化。索引能压到原大小的十分之一左右,内存完全放得下,但召回率掉一截,需要用 rerank 补。
我的结论是:数据量到千万级,量化几乎是必选项,不然内存成本压不住。
第四档:5000 万条以上——托管或分布式
这档自己搭性价比开始明显下降:索引构建要几小时甚至几天,扩容要重新分片,出问题很难查。
托管服务在这里的价值不是"性能更好",而是省掉了索引迁移和扩容的运维。它在检索性能上不会比自建强,甚至可能因为网络层更弱而略慢。它换回来的是三样东西:不停机扩容、备份恢复、以及你不用在凌晨处理重建索引的告警。
一个反直觉的发现:索引构建比查询更费事
我原以为向量库难在查询,实际难在构建和更新。
十万条建索引几秒钟,一千万条要几小时。这期间 CPU 打满、内存吃紧、磁盘 IO 拉满,而且不能中断——中断了从头再来。
更麻烦的是更新。HNSW 这类图索引删一条向量成本很高,官方做法是打标记(tombstone)再定期重建。标记积累到一定程度,查询准确率和速度都会退化。
所以我的实践是:
- 数据更新不频繁的,直接全量重建。删掉旧索引文件重建一份新的,切换过去
- 数据量太大没法全量重建的,得规划 tombstone 清理周期
- 索引构建一定放在业务低峰期,并准备好多个副本并行构建——构建速度接近线性,单机 12 小时的任务,八台机器一小时就完事
怎么判断你该换档
三个信号,出现任意一个就该考虑升级:
- 内存占用到了机器的 70% 以上,且还在涨
- 索引构建时间超过你的可接受窗口(我用的标准是 4 小时)
- 开始需要向量过滤和向量检索组合,且过滤条件的基数很杂
第三个信号容易被忽略。如果业务需要"先按租户过滤,再在租户内做向量检索",纯 ANN 索引就不够用了,得用带过滤能力的引擎,或者在应用层按租户切分索引。
我现在用的判断规则
一句话:先算内存,再算条数,最后才看产品名。
- 内存放得下,只有主应用在查 → 进程内库,别折腾
- 放得下,多服务要查 → 单机服务,资源划死
- 放不下 → 先想量化能不能解决,能解决就单机 + 量化
- 放不下且量化也不够 → 托管或分布式
选完之后一定要做一件事:用真实数据建一遍索引,量一下构建时间和查询 P99。厂商给的是最优情况下的数字,你自己的数据分布才是唯一有意义的参考。
各家托管服务的定价档位和数据量上限变动很快,这个分档思路是稳定的,但落到具体产品上还得看当下的官方页面。