选向量数据库的时候纠结了两周。当时手里有三个方案:Chroma看起来最轻量,Milvus文档最厚感觉最专业,pgvector因为已经用了PostgreSQL所以最省事。最后三个都部署了一遍,踩了一圈坑,结论是:没有最好的,只有最合适的;
这篇文章把三个方案的实际部署过程和对比写出来,帮你少走弯路;
Chroma:原型阶段的最佳选择
Chroma最大的优点是零配置。几行Python代码就能跑起来,不需要装额外的服务;
import chromadb
# 持久化模式——数据存在本地磁盘
client = chromadb.PersistentClient(path="./chroma_data")
collection = client.get_or_create_collection(
name="documents",
metadata={"hnsw:space": "cosine"}
)
# 添加数据
collection.add(
documents=["Python是一种通用编程语言", "Docker是容器化部署工具"],
metadatas=[{"category": "language"}, {"category": "devops"}],
ids=["doc1", "doc2"]
)
# 查询
results = collection.query(query_texts=["什么是编程语言"], n_results=2)
print(results["documents"])
也可以作为独立服务运行,供多个客户端连接:
pip install chromadb
chroma run --path ./chroma_data --host 0.0.0.0 --port 8100
客户端用HttpClient连上去就行;
适用场景:快速原型验证、个人项目、数据量在百万级以下。不适合:高并发生产环境、需要水平扩展的场景;
pgvector:已有PostgreSQL的最佳选择
如果你已经在用PostgreSQL,pgvector是最自然的选择——不需要额外部署和维护一个数据库;
-- 启用扩展
CREATE EXTENSION IF NOT EXISTS vector;
-- 创建表
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
content TEXT NOT NULL,
metadata JSONB DEFAULT '{}',
embedding vector(768)
);
-- 创建HNSW索引
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 200);
Python操作用psycopg2加pgvector扩展:
import psycopg2
from pgvector.psycopg2 import register_vector
import numpy as np
conn = psycopg2.connect("dbname=mydb user=postgres")
register_vector(conn)
cur = conn.cursor()
# 插入
embedding = np.random.rand(768).tolist()
cur.execute(
"INSERT INTO documents (content, embedding) VALUES (%s, %s)",
("测试文档", embedding)
)
# 相似度搜索
query = np.random.rand(768).tolist()
cur.execute(
"""SELECT content, 1 - (embedding <=> %s::vector) as sim
FROM documents ORDER BY embedding <=> %s::vector LIMIT 5""",
(query, query)
)
适用场景:已有PostgreSQL基础设施、数据量在千万级以下、不想维护额外的数据库。不适合:超大规模数据(亿级)、需要极致的向量检索性能;
Milvus:生产环境的首选
Milvus是三个方案中最专业的,专门为大规模向量检索设计;
Docker部署需要三个组件:
version: "3.5"
services:
milvus:
image: milvusdb/milvus:v2.5.6
command: ["milvus", "run", "standalone"]
environment:
ETCD_ENDPOINTS: etcd:2379
MINIO_ADDRESS: minio:9000
volumes:
- milvus_data:/var/lib/milvus
ports:
- "19530:19530"
depends_on: [etcd, minio]
etcd:
image: quay.io/coreos/etcd:v3.5.18
minio:
image: minio/minio:RELEASE.2024-11-07
environment:
MINIO_ACCESS_KEY: minioadmin
MINIO_SECRET_KEY: minioadmin
volumes:
milvus_data:
Python操作:
from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType
connections.connect(host="localhost", port="19530")
fields = [
FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True),
FieldSchema(name="content", dtype=DataType.VARCHAR, max_length=2000),
FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=768)
]
schema = CollectionSchema(fields)
collection = Collection("documents", schema)
index_params = {"metric_type": "COSINE", "index_type": "HNSW",
"params": {"M": 16, "efConstruction": 256}}
collection.create_index("embedding", index_params)
适用场景:大规模生产环境、高并发查询、需要水平扩展。缺点:部署复杂度高(需要etcd和MinIO)、学习成本相对较高;
对比总结
| 维度 | Chroma | pgvector | Milvus |
|---|---|---|---|
| 部署难度 | 最简单 | 简单(需已有PG) | 较复杂 |
| 适用数据量 | <百万 | <千万 | 亿级 |
| 并发能力 | 弱 | 中 | 强 |
| 扩展性 | 单机 | 依赖PG扩展 | 分布式 |
| 生态集成 | LangChain原生 | SQLAlchemy/Django | PyMilvus |
我的建议是:先用Chroma把流程跑通,验证RAG的效果。等量上来了、需要上线了,再根据你的基础设施选pgvector或Milvus。