为什么我在 Agent 项目里只认 PostgreSQL:向量搜索篇
最近有个朋友问我:做 Agent 项目,向量搜索用什么方案?我毫不犹豫地说:PostgreSQL + VectorChord。
他有点意外:“不用 Milvus、Pinecone 这些专用向量数据库?”
这让我意识到,很多人对 Agent 时代的向量存储需求有误解。今天我就聊聊为什么我在 Agent 项目里只认 PostgreSQL,以及 VectorChord 如何实现低成本亿级向量检索,对比传统 HNSW 方案的优势。
Agent 时代,向量存储需要什么?
在聊技术之前,先想想 Agent 项目的特点:
1. 知识库频繁更新
Agent 的知识库不是静态的。用户不断上传新文档、新对话历史,向量索引需要频繁重建。传统 HNSW 索引构建 1 亿向量需要数小时,这根本跟不上更新节奏。
2. 规模快速增长
Agent 应用的向量规模往往和用户活跃度、文档数量成正比。
从实际场景来看:
-
个人知识库:个人笔记、文档、邮件等场景,向量规模通常在 10 万 ~ 100 万 级别。单个用户的文档总量有限,即使加上增量更新,百万级向量已经能覆盖绝大多数个人场景。
-
企业 Agent 应用:这是向量规模真正爆发的场景。客服机器人需要存储所有产品文档、历史对话、FAQ;企业知识库问答需要覆盖内部 wiki、工单记录、会议纪要;员工助手需要访问邮件、文档、代码库。随着业务增长,向量规模很容易达到 千万甚至亿级。比如一个中型企业(1000-5000 人)的知识库,文档数量百万级,分块后向量规模轻松破千万。
-
Agent 长期记忆需求:随着 OpenClaw、Codex 等 Agent 框架的普及,Agent 作为"数字员工"需要持久化记忆的内容远超传统 RAG:
- 完整对话历史:每次对话都需要向量化存储,用于上下文检索和一致性保持
- 任务记忆:cron 任务、待办事项、长期目标及其执行状态
- 用户偏好记忆:沟通风格、决策模式、关注重点需要被记住并复用
- 知识更新:每次交互中学习的新信息都需要纳入知识库
这类记忆型内容会随着 Agent 使用时间持续累积,一个活跃使用半年的 Agent,仅对话记录就可能产生数百万向量。
这给向量存储方案带来了可扩展性挑战。
3. 成本敏感
大多数 Agent 项目还是早期阶段,没有大规模盈利。为了向量搜索单独维护一套专用数据库,无论是成本还是运维都是负担。
4. 数据一致性
Agent 的向量数据往往和业务数据(用户、文档、对话记录)强相关。分开存储会带来一致性问题和数据同步的复杂性。
基于这些特点,我的选择标准很清晰:
- 构建要快:能应对频繁更新
- 成本要低:小团队也能用得起
- 已在技术栈内:不引入额外组件
- 够用就好:不追求极致性能
专用向量数据库的问题
先说说我为什么不选专用向量数据库。
在向量数据库选型时,很多人会第一时间考虑 Milvus、Pinecone、Weaviate 等专用方案。但实际使用中,这些方案在 Agent 场景下暴露出明显问题:
| 问题 | 具体表现 |
|---|---|
| 成本高 | 1 亿 768 维向量需要 >$1000/月,内存占用 >100GB |
| 构建慢 | HNSW 索引构建 1 亿向量需要 >10 小时 |
| 运维复杂 | 需要额外部署、监控、备份 |
| 数据分散 | 向量数据和业务数据分离,一致性问题 |
对于大多数 Agent 项目来说,这些问题都是不可接受的。这也是为什么我在 RAG 向量检索方案对比中,更倾向于 PostgreSQL 原生方案。
VectorChord:PostgreSQL 原生的答案
VectorChord 是我们团队(TensorChord)推出的 PostgreSQL 原生向量搜索扩展,是 pgvecto.rs 的继任者。
先看个对比:
| 方案 | 1 亿 768 维存储 | 构建时间 | 内存占用 | 成本(每月) |
|---|---|---|---|---|
| 专用向量数据库 (HNSW) | ~1000GB | >10 小时 | >100GB | ~$1000+ |
| VectorChord (IVF+RaBitQ8) | ~100GB | ~20 分钟 | <1GB | ~$247 |
成本只有 1/5,构建速度提升 30x。这才是 Agent 项目需要的。
核心技术:为什么能做到这么快这么省?
IVF + RaBitQ:放弃 HNSW 的理由
HNSW 的多层图结构确实查询速度快,但有几个致命问题:
- 内存占用巨大:每个节点需要存储多层邻居信息,内存占用是向量本身的数倍
- 构建慢:需要逐个插入节点并维护多层图结构
- 不适合磁盘:频繁的随机访问模式在磁盘上性能很差
VectorChord 采用 IVF(倒排索引)+ RaBitQ(随机化比特量化)的组合:
- 存储压缩比高:1bit 量化压缩率 32x,8bit 量化压缩率 4x
- 构建速度快:流式构建,不需要全量数据在内存中
- 磁盘友好:按簇连续存储,顺序 IO 优化
存储布局:顺序 IO + 缓存友好的两层设计
这是 VectorChord 最核心的设计之一,直接借鉴了 列存数据库 的设计思路。
全局:按簇连续存储
整个索引的量化向量按簇顺序存储在 PostgreSQL 数据页中,结构如下:
|
|
查询时只需要读取候选簇对应的连续存储区域,是顺序 IO而非随机 IO。这种设计借鉴了 LSM-Tree 的顺序写入思路,磁盘吞吐量提升 5~10 倍。
簇内:类列存布局
传统行存(每个向量连续放所有维度):
|
|
VectorChord 簇内类列存:
|
|
同一维度的所有向量量化数据连续存放,计算距离时可以连续加载到 SIMD 寄存器。CPU 缓存命中率从 ~30% 提升到 ~95%。
内存磁盘分层
极致压缩内存占用:只有几千个聚类质心全精度存放在内存中,几千个 768 维质心只需要 ~12MB 内存。
所有量化向量都存放在磁盘上,查询时只加载候选簇的数据。1 亿向量索引,全程内存占用不到 1GB。
RaBitQ:带理论保证的低比特压缩
RaBitQ 来源于论文 RaBitQ: Quantizing High-Dimensional Vectors with a Theoretical Error Bound for Approximate Nearest Neighbor Search,核心创新是通过随机旋转让维度独立,量化后误差有严格理论上界,在相同压缩率下召回率比传统低比特量化高 5%~10%。
我们用一个 2 维向量的完整例子走一遍量化流程:
步骤 1:训练集中心化
对整个训练集的所有向量,每个维度减去该维度的均值,消除偏移。这是 Standardization 的常用技巧。
|
|
步骤 2:随机正交旋转
生成一个随机正交矩阵 R(满足 R^T * R = I),对中心化后的向量做旋转。旋转后各个维度的分布会更接近独立同分布,方便后续量化和误差控制。
|
|
步骤 3:量化到低比特
- 1bit 量化:只存符号,≥0 存 +1,<0 存 -1
- 4bit 量化:划分 16 个区间,每个维度存 4bit 区间索引
- 8bit 量化:划分 256 个区间,每个维度存 8bit 区间索引
我们演示 1bit 量化:
|
|
| 量化 | 压缩率 | 召回损失 | 适用场景 |
|---|---|---|---|
| 1bit RaBitQ | 32x | ~5%~8% | 超大规模,成本极致敏感 |
| RaBitQ4 | 8x | ~2%~3% | 大规模,平衡成本精度 |
| RaBitQ8 | 4x | <1% | 大多数生产场景 |
流式构建:128GB 内存构建 10 亿级索引
VectorChord 最大的亮点:流式磁盘构建。
|
|
- 采样 20%-30% 向量做双层 K-Means 聚类
- 顺序扫描全量数据,边读边写,内存只保留当前批次
- 1 亿 768 维向量索引构建仅需 20 分钟
为什么 PostgreSQL 原生这么重要?
完全兼容 pgvector 的数据类型和查询语法,现有业务可以零成本迁移。
更重要的是,向量数据和业务数据在同一套数据库里:
- 不需要数据同步
- 事务一致性有保障
- 运维成本不增加
- 已经在用的技术栈,不需要学习新东西
对于小团队来说,这意味着可以快速上线,而不是花时间在基础设施上。
这也是 PostgreSQL 作为 Pinecone 替代方案的优势——无需引入新的技术栈,直接在现有数据库上扩展向量检索能力。
查询性能:够用就好
有人可能会问:PostgreSQL 原生能有多快?
VectorChord 的查询流水线:
|
|
预过滤支持:解决过滤后空结果问题
VectorChord 支持业务非常常用的「先过滤条件后向量搜索」场景,并且有两种过滤模式:
| 模式 | 流程 | 优势 | 适用场景 |
|---|---|---|---|
| 预过滤 | 先执行 SQL 条件过滤,再对过滤后的向量做搜索 | 只计算满足条件的向量,大幅减少距离计算量 | 过滤条件严格,会过滤掉 90% 以上数据 |
| 后过滤 | 先做向量搜索取出远多于需求的候选,再做 SQL 过滤 | 保证能返回足够的结果,不会轻易空 | 过滤条件宽松,需要保证结果数量 |
通过分批扩展 + Fallback 机制,VectorChord 解决了「过滤后没有结果」的异常问题:不会一次只取固定 n 个候选簇就结束,而是按距离排序分批取出,如果当前批次过滤后结果不足,自动取出下一批候选继续处理。
对于大多数 Agent 应用来说,这个性能完全够用。而且成本只有专用方案的 1/5。
我的选型建议
基于实际经验,我给 Agent 项目的向量搜索选型建议:
规模 < 1000 万
- 直接用 pgvector + HNSW
- 单机 PostgreSQL 完全够用
规模 1000 万 ~ 1 亿
- VectorChord + RaBitQ8
- 单机或主从架构
规模 > 1 亿
- VectorChord + RaBitQ4/RaBitQ1
- 考虑分库分表或读写分离
技术细节:双层 K-Means 设计
VectorChord 当前采用双层 K-Means 聚类来构建 IVF 索引:
- 第一层先聚
√k个中观簇 - 每个中观簇内部再聚类,得到最终 k 个簇
整体计算量从 O(n * k * d) 降到 O(n * d * √k)。比如 k=4096,计算量直接减少 64 倍。
这种分层结构本身就来自 Hierarchical SuperKMeans,VectorChord 已经落地了这部分。迭代内剪枝是 SuperKMeans 最大的创新,是未来的演进方向。
未来演进:集成 SuperKMeans + PDX
VectorChord 还在快速演进中,有几个值得期待的方向:
SuperKMeans:构建速度再快 30x
SuperKMeans 的核心创新是在每轮 K-Means 迭代内部做渐进式剪枝:
- 只计算前 d’(12%~25%)维度,用 BLAS GEMM 批量计算
- 基于部分维度距离剪掉 97% 以上不可能的候选
- 只对剩下 3% 的候选计算完整维度距离
性能预估:集成 SuperKMeans 后,1 亿 768 维向量构建时间可以从 20 分钟降到 2~3 分钟。
PDX 布局:搜索 QPS 再提升 200%~300%
PDX 是 CWI 团队提出的列存布局优化,VectorChord 当前簇内列存已经有了类似思路:
- 垂直块:前 25% 维度完全列存,专门用于快速剪枝
- 水平块:剩余维度按 64 维分组列存
缓存命中率和剪枝效率进一步提升,搜索 QPS 预计还能再提升 200%~300%。
Thoughts
够用主义 vs 极致性能
Agent 项目早期,最重要的是快速验证和迭代,而不是追求极致的查询性能。
VectorChord 的设计哲学就是"够用就好”:在保证可接受的精度和延迟的前提下,把存储和成本打到极低。
这种务实的态度,才是小团队生存之道。
PostgreSQL 是 Agent 时代的最佳数据底座
向量搜索只是 PostgreSQL 众多能力中的一个。
后面我还会聊聊:
- 全文检索:PostgreSQL 的 FTS 为什么比 ES 更适合 Agent 项目
- ACID 事务:为什么 Agent 状态管理离不开事务
- JSONB:为什么我偏好 JSONB 而不是单独的 MongoDB
- OLAP 场景:Postgres 在分析型场景下的探索
- Supabase:为什么我推荐开发者从 Supabase 入手
- 等
Next Step
VectorChord 还在快速演进中:
- 集成 SuperKMeans 迭代内剪枝,构建速度再快 30x
- 集成 PDX 布局,搜索 QPS 再提升 200%~300%
但核心思路不会变:PostgreSQL 原生 + 低成本 + 够用就好。
这是"为什么我在 Agent 项目里只认 PostgreSQL"系列的第一篇。下一篇聊聊全文检索。