内存/Redis/PGVector/Milvus/ES 怎么选?Spring AI VectorStore 抽象与向量库选型对照表
系列:Spring AI 深入浅出(第 10 篇)
版本:Spring AI 2.0.1 / Spring Boot 4.1.x / JDK 21
标签:#SpringAI #向量库 #PGVector #RAG
前置阅读:第 9 篇《RAG 原理与 ETL 管线》
预计字数:6500 字|可复制源码 + 选型对照表 + 踩坑 FAQ
本文将解决:VectorStore一个抽象换掉,RAG 代码不用改;难的是选对库。本文给你一张照着选的对照表,并用 PGVector 跑通接入。
你将学到:
VectorStore可移植抽象(2.0 统一,覆盖 20+ 数据库)- SQL-like 元数据过滤(
FilterExpression) - 各向量库选型对照表(内存/PGVector/Redis/Milvus/ES)
- embedding 模型选择与维度一致性
- PGVector 完整接入实战
一、版本标注
本文基于 Spring AI 2.0.1 / Boot 4.1 / JDK 21。2.0 把VectorStore统一成一个覆盖 20+ 数据库的可移植抽象,具体各实现的配置项以 2.0.1 官方文档为准。
二、VectorStore 可移植抽象
第 9 篇的 ETL 里,业务代码只和VectorStore接口打交道:
publicinterfaceVectorStore{voidadd(List<Document>documents);// 入库(内部会向量化)List<Document>similaritySearch(SearchRequestrequest);// 相似度检索}换库 = 换VectorStore的实现 Bean,业务代码零改动:
业务代码 ↓ 只依赖接口 VectorStore 接口 ├── SimpleVectorStore(内存,测试用) ├── PgVectorStore(PostgreSQL) ├── RedisVectorStore ├── MilvusVectorStore ├── ElasticsearchVectorStore └── ...(20+ 实现)三、SQL-like 元数据过滤
向量检索不能只按相似度,还要能按业务字段过滤(如"只看工程部文档")。Spring AI 用FilterExpression提供类似 SQL 的过滤:
importorg.springframework.ai.vectorstore.filter.FilterExpressionBuilder;FilterExpressionfilter=newFilterExpressionBuilder().eq("department","engineering")// 等于.and().gte("year",2024)// 大于等于.build();FilterExpression会翻译成各向量库自己的过滤语法,配合检索请求使用(第 11 篇展开)。
四、各向量库选型对照表
| 库 | 形态 | 规模 | 过滤能力 | 部署成本 | 适用 |
|---|---|---|---|---|---|
SimpleVectorStore | 内存 | 极小 | 基础 | 零 | 本地开发/单测 |
| PGVector | PostgreSQL 扩展 | 中 | SQL 强 | 低(已有 PG 则免费) | 中小规模、已有 PG |
| Redis | 内存+持久化 | 中 | 中等 | 低 | 低延迟、已有 Redis |
| Milvus | 专用向量库 | 大 | 强 | 高(独立集群) | 亿级向量、专业检索 |
| Elasticsearch | 搜索引擎 | 中 | 强(全文+向量混合) | 中 | 需要混合检索/全文 |
决策口诀:
- 还没定、想快速验证 →
SimpleVectorStore(内存) - 团队已有 PostgreSQL →PGVector(几乎零新增成本,最常用)
- 团队已有 Redis / 要极致延迟 → Redis
- 向量规模大、要专业检索 → Milvus
- 要全文 + 向量混合检索 → Elasticsearch
五、embedding 模型选择与维度一致性
向量库存的是 embedding 向量,维度由 embedding 模型决定,必须和库的建表维度一致。
选择 embedding 模型看三点:
- 维度:常见 768 / 1024 / 1536 等,选定后库建表要一致
- 中文效果:中文场景选中文友好的模型(如 BGE 系列)
- 本地 vs 云端:本地(如 Ollama 的 embedding 模型)免费但需硬件;云端效果好
经验:先定 embedding 模型,再按它的维度建库;中途换模型=换维度=要重建索引,代价大,所以要早定。
六、PGVector 接入实战
6.1 依赖
<!-- PGVector 向量库 --><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-vector-store-pgvector</artifactId></dependency><!-- PostgreSQL 驱动 --><dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId></dependency>6.2 建库(先开扩展 + 建表)
-- 启用 pgvector 扩展CREATEEXTENSIONIFNOTEXISTSvector;建表语句(含向量列,维度与 embedding 模型一致,如 1024):
CREATETABLEIFNOTEXISTSvector_store(id uuidPRIMARYKEY,contenttext,metadata json,embedding vector(1024));6.3 配置与使用
spring:datasource:url:jdbc:postgresql://localhost:5432/aiusername:postgrespassword:postgres业务代码和第 9 篇完全一样,只是VectorStore的实现换成了PgVectorStore(由 starter 自动装配,具体 Bean 配置以 2.0.1 文档为准)。
七、原理图解:VectorStore 抽象层
换库 = 换 B 下面一个节点,A 之上纹丝不动。
八、踩坑 FAQ
坑 1:PGVector 没开扩展
现象:接入 PGVector 后报找不到 vector 类型。
原因:没执行CREATE EXTENSION vector。
解决:先在目标库执行扩展语句,再建表。
坑 2:维度不一致,写入失败
现象:入库报向量维度不匹配。
原因:embedding 模型输出维度 ≠ 建表vector(N)的维度。
解决:核对 embedding 维度,重建表(改vector(N))。
坑 3:metadata filter 表达式语法错
现象:过滤查询报错或结果为空。
原因:FilterExpressionBuilder的字段名/操作符和元数据对不上。
解决:确认元数据的 key 名一致,用.eq()/.and()/.gte()等组合;核对各库翻译后的语法。
坑 4:用内存库跑测试,数据不持久
现象:SimpleVectorStore重启数据就没了。
原因:内存实现,本来就是测试用。
解决:生产用 PGVector/Milvus 等持久化实现。
坑 5:切换向量库后,已有的向量要重建
现象:从内存切到 PGVector,发现要重新入库。
原因:向量库之间不通用,切换=重新跑 ETL。
解决:尽早定库;ETL 写成可重跑的幂等脚本,切库后一键重建。
九、小结与合集导航
本篇核心:面向VectorStore接口编程,用一张对照表选对库。
VectorStore可移植抽象(2.0 统一,20+ 实现)FilterExpression做 SQL-like 元数据过滤- 选型口诀 + embedding 维度一致性
- PGVector 完整接入
下一篇:《QuestionAnswerAdvisor 检索优化》——RAG 答非所问/幻觉怎么破,从召回优化讲起。
十、互动钩子
投票:你生产用哪个向量库?
- 还没定/内存
- PGVector
- Redis
- Milvus
- Elasticsearch
评论区聊聊你的向量库选型理由;源码见置顶评论。