选向量数据库的时候纠结了两周。当时手里有三个方案: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。