第03章:数据库选型——PostgreSQL+pgvector与ChromaDB对比
第03章:数据库选型——PostgreSQL+pgvector与ChromaDB对比
3.1 选型原则:不要为了技术复杂度买单
数据库选型是企业级AI项目里最容易被"过度设计"的环节。选型时有两个核心原则:
- 能跑通再优化:先用最简单的方案跑通核心流程,瓶颈出现再针对性升级
- 团队能维护:选团队真正能驾驭的工具,不是理论上最优的工具
本章对比三种向量存储方案,帮助你在不同场景下做正确选择。
3.2 方案一:PostgreSQL + pgvector(推荐生产方案)
pgvector 是 PostgreSQL 的扩展,在PG里直接支持向量类型和向量索引。
核心优势
- 单一数据库:结构化数据(顾客档案)和向量数据(知识库embedding)在同一个库,省去同步麻烦
- ACID保障:事务支持完整,数据一致性与PostgreSQL同级别
- SQL全家桶:JSONB、全文搜索、窗口函数……全部可用
- 运维简单:一个数据库实例搞定所有,不用多跑一套Milvus/Chroma服务
- 社区成熟:PG16+pgvector的生产案例已经很多,踩坑成本低
局限性
- pgvector 的 ANN 索引(IVF-Flat、HNSW)在超大规模数据量(>1亿条)下性能不如专业向量数据库
- 安装需要数据库服务器支持扩展(部分云PG厂商暂不支持)
安装方式
# Docker 方式(一键)
docker pull pgvector/pgvector:pg16
docker run -d --name pgvector \
-e POSTGRES_PASSWORD=yourpassword \
-p 5432:5432 \
pgvector/pgvector:pg16
# 已有的PG实例追加扩展
CREATE EXTENSION IF NOT EXISTS vector;
# 向量字段定义(1536维,适配 bge-small-zh/bge-base 等)
ALTER TABLE medical_knowledge
ADD COLUMN embedding vector(1536);
# 创建 HNSW 索引(查询性能更好)
CREATE INDEX ON medical_knowledge
USING hnsw (embedding vector_cosine_ops);
# 创建 IVF-FLAT 索引(内存占用更低)
CREATE INDEX ON medical_knowledge
USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
增删改查示例
-- 插入带向量
INSERT INTO medical_knowledge (title, content, category, embedding)
VALUES (
'光子护理适合人群',
'光子护理适合面部有雀斑、晒斑、毛孔粗大、肤色不均的人群。敏感肌需谨慎。',
'抗衰',
'[0.123, -0.456, ...]' -- 1536维向量
);
-- 相似性检索(余弦相似度)
SELECT title, content,
1 - (embedding <=> '[0.1, 0.2, ...]'::vector) AS similarity
FROM medical_knowledge
WHERE category = '抗衰'
ORDER BY embedding <=> '[0.1, 0.2, ...]'::vector
LIMIT 5;
-- 过滤 + 向量检索组合
SELECT * FROM medical_knowledge
WHERE forbidden = FALSE
AND category = '抗衰'
ORDER BY embedding <=> '[query_vector]'::vector
LIMIT 3;
3.3 方案二:ChromaDB(轻量原型方案)
ChromaDB 是一个专门为 AI 应用设计的向量数据库,安装简单,API直观,适合快速原型验证。
核心优势
- 零配置:pip install 后直接用,不需要跑服务器
- API 极简:add/query/delete 三条命令搞定所有操作
- 自带持久化:本地文件存储,重启不丢数据
- Python 原生:和 Pandas/NumPy 无缝衔接
局限性
- 纯向量库,没有结构化字段(顾客档案等仍需存在PG里,形成双库架构)
- 并发写入性能一般(单实例,写入需要加锁)
- 删改查的灵活性不如 pgvector(不支持复杂过滤条件)
- 部署在生产环境时需要封装成独立服务
安装与使用
# 安装
pip install chromadb
# 基本使用
import chromadb
client = chromadb.PersistentClient(path="./chroma_data")
# 创建集合(类似表)
collection = client.create_collection(
"medical_knowledge",
metadata={"description": "美业知识库"}
)
# 添加向量数据
collection.add(
ids=["kg_1", "kg_2"],
embeddings=[[0.1, 0.2, ...], [0.3, 0.4, ...]], # 向量
documents=["光子护理适合人群...", "水光针适合人群..."], # 原文
metadatas=[{"category": "抗衰"}, {"category": "抗衰"}]
)
# 语义检索
results = collection.query(
query_embeddings=[[0.15, 0.22, ...]],
n_results=3
)
# results["documents"][0] → 最相似的3条知识
双库架构下的数据一致性
当知识库同时存在 PG 和 ChromaDB 时,新增/修改/删除操作必须双写:
def add_knowledge(title, content, category):
pg_id = insert_into_pg(title, content, category) # 写PG
vector = get_embedding(f"{title}:{content}") # 生成向量
add_to_chroma(f"kg_{pg_id}", vector, content) # 写ChromaDB
def delete_knowledge(pg_id):
delete_from_pg(pg_id) # 删PG
delete_from_chroma(f"kg_{pg_id}") # 删ChromaDB
3.4 方案三:混合方案(大型项目)
当项目规模变大,可以考虑:
| 数据类型 | 存储方案 |
|---|---|
| 顾客档案、订单(结构化+事务) | PostgreSQL(已有) |
| 知识库向量(>100万条) | Qdrant / Milvus(专用向量库) |
| 缓存热点数据 | Redis |
| 文件(文档、图片) | S3 / MinIO |
Qdrant 是这两年表现很不错的开源向量数据库,有 Rust 和 Python 客户端,支持过滤条件,生产性能优秀。
3.5 三方案横向对比
| 维度 | pgvector | ChromaDB | Qdrant/Milvus |
|---|---|---|---|
| 安装难度 | 中(需PG扩展) | 低(pip即用) | 高(需单独部署) |
| 结构化+向量 | ✅ 单一数据库 | ❌ 需双库 | ❌ 需双库 |
| 查询灵活性 | ✅ 极致(SQL) | ⚠️ 弱 | ⚠️ 中等 |
| 百万级向量性能 | ⚠️ 中等 | ❌ 差 | ✅ 优秀 |
| 事务支持 | ✅ 完整ACID | ❌ 无 | ❌ 无 |
| 团队熟悉度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ |
| 推荐场景 | 生产首选 | 原型/轻量 | 超大规模 |
本书实战选择:先用 ChromaDB 跑通原型(美容案例就是用的这个),等数据量超过50万条时平滑迁移到 pgvector 或 Qdrant。
3.6 Embedding 模型与向量维度
向量维度由 Embedding 模型决定,选型时必须匹配:
| 模型 | 向量维度 | 中文支持 | 推荐场景 |
|---|---|---|---|
| bge-small-zh | 512 | ✅ 强 | 轻量/快速(本书用这个) |
| bge-base-zh | 768 | ✅ 强 | 平衡(推荐) |
| text2vec-base-chinese | 768 | ✅ 强 | 平衡 |
| m3e-base | 768 | ✅ 强 | 平衡 |
| bge-large-zh | 1024 | ✅ 强 | 高精度 |
注意:ChromaDB 建 Collection 时会根据首次插入的数据自动推断向量维度。如果 Ollama 的 Embedding 模型输出维度与已有 Collection 不匹配,会报 dimension 错误。删除
chroma_data/目录重建即可。
落地动作
- 确认你的 PostgreSQL 是否支持 pgvector 扩展(如果没有,用 Docker 拉取官方镜像)
- 用 pip 安装 chromadb,
python -c "import chromadb; print(chromadb.__version__)"验证 - 运行一次本地的向量插入和检索测试(参考本章代码)
- 如果数据量预估 >50万,提前规划 pgvector 迁移路径