Embedding 与向量数据库:模型选型、PGVector/Milvus/Chroma 对比

在 RAG(Retrieval-Augmented Generation)系统的技术栈中,Embedding 模型向量数据库构成了检索能力的两大基石。前者决定了文本能否被精确地表示为数学向量,后者决定了这些向量能否被高效地存储和检索。选型不当的 Embedding 模型会导致语义匹配失准,而选型不当的向量数据库则会在规模增长时成为系统瓶颈。

本文面向正在构建或优化 RAG 系统的工程师,从 Embedding 模型的技术栈出发,深入对比主流向量检索算法,对 PGVector、Milvus、Chroma 三大开源方案做深度剖析,并提供涵盖 Pinecone、Weaviate、Qdrant 等方案的全景选型参考。


一、Embedding 模型技术栈

1.1 主流 Embedding 模型全景

模型提供商维度最大 Token多语言部署方式MTEB 排行(均分)定价(每百万 Token)
text-embedding-3-smallOpenAI1536(可缩减)8191API~62.3$0.02
text-embedding-3-largeOpenAI3072(可缩减)8191API~64.6$0.13
embed-v3Cohere1024512API~64.5$0.10
BGE-M3BAAI10248192本地/API~64.0开源免费
GTE-Qwen2-7B-instruct阿里15368192本地~65.4开源免费
Jina Embeddings v3Jina AI1024(可缩减)8192API/本地~64.3$0.02

MTEB(Massive Text Embedding Benchmark) 是目前最权威的 Embedding 评测基准,覆盖分类、检索、聚类、STS 等 8 大任务类型、56+ 数据集。上述分数为 Retrieval 子任务的平均分,数据来源为 MTEB Leaderboard(2024Q4)。

1.2 模型选型决策框架

OpenAI text-embedding-3 系列

OpenAI 的 text-embedding-3 系列是当前使用最广泛的 Embedding API。其核心优势在于:

  • 维度缩减(Matryoshka):通过 dimensions 参数在不重新训练的前提下缩减向量维度,例如将 3072 维缩减为 1024 维,存储成本降低 67%,精度损失控制在 2-3% 以内
  • 超长上下文:支持 8191 Token 输入,适合处理较长的文档片段
  • 生态优势:与 OpenAI 全栈工具链(Function Calling、Fine-tuning)无缝集成
from openai import OpenAI

client = OpenAI()

response = client.embeddings.create(
    model="text-embedding-3-large",
    input="向量数据库选型需要综合考虑性能、成本和运维复杂度",
    dimensions=1024
)

vector = response.data[0].embedding
print(f"维度: {len(vector)}")  # 1024

成本对比:text-embedding-3-small($0.02/百万 Token)的性价比远高于 text-embedding-3-large($0.13/百万 Token)。对于大多数 RAG 场景,small 版本已经足够。只有在对检索精度有极致要求的场景(如法律、医疗知识库),才值得投入 6.5 倍的成本使用 large 版本。

Cohere embed-v3

Cohere embed-v3 的差异化在于其任务分离设计——同一模型可以根据任务类型(search_documentsearch_queryclassificationclustering)生成不同表示,提升特定任务的表现:

import cohere

co = cohere.ClientV2(api_key="your-api-key")

response = co.embed(
    texts=["RAG 系统架构设计", "检索增强生成技术原理"],
    model="embed-v3",
    input_type="search_document",
    embedding_types=["float"],
    dimensions=1024
)

注意事项:Cohere 的最大输入长度仅 512 Token,这是其主要短板。如果文档片段普遍较长,需要在切分策略上做更多工作。

BGE-M3(BAAI)

BGE-M3 是目前开源 Embedding 模型中综合能力最强的选择,其独特之处在于三合一架构:

  • 稠密向量(Dense):标准的语义检索表示
  • 稀疏向量(Sparse):类似 BM25 的词频表示,通过 learned sparse encoding 实现
  • 多向量表示(Multi-vector):类似 ColBERT 的 Token 级别表示
from sentence_transformers import SentenceTransformer

model = SentenceTransformer("BAAI/bge-m3")

docs = [
    "Milvus 是一款开源的分布式向量数据库",
    "PGVector 是 PostgreSQL 的向量检索扩展",
]

dense_embeddings = model.encode(docs, normalize_embeddings=True)

output = model.encode(
    docs,
    pooling="cls",
    sparse_format="coo"
)
sparse_embeddings = output["lexical_weights"]

BGE-M3 的 8192 Token 上下文窗口配合混合检索能力,使其成为自建 RAG 系统的首选模型。唯一需要注意的是其 7B 参数量带来的推理成本——在没有 GPU 的服务器上,单条编码耗时可能达到秒级。

GTE-Qwen2(阿里)

GTE-Qwen2 基于通义千问的底层架构,在中英文双语场景中表现均衡。其 7B 版本在 MTEB 排行上成绩优异(均分 65.4),但 1.5B 的轻量版本在性价比上更为突出——推理速度快 4-5 倍,精度损失控制在 3% 以内。

from FlagEmbedding import BGEM3FlagModel

model = BGEM3FlagModel("BAAI/bge-m3", use_fp16=True)

docs = ["如何配置 HNSW 索引", "PGVector 安装与部署指南"]
query = "向量数据库索引配置方法"

doc_embeddings = model.encode(docs, batch_size=32)
query_embedding = model.encode([query])

Jina Embeddings v3

Jina Embeddings v3 的特色在于其任务自适应的 LoRA 适配器机制——同一基础模型可以根据不同任务(检索、分类、聚类)加载不同的 LoRA 权重,实现一个模型覆盖多种用途:

import requests

def jina_embed(texts, task="retrieval"):
    url = "https://api.jina.ai/v1/embeddings"
    headers = {"Authorization": "Bearer your-jina-api-key"}
    data = {
        "model": "jina-embeddings-v3",
        "input": texts,
        "task": task,
        "dimensions": 1024
    }
    response = requests.post(url, json=data, headers=headers)
    return response.json()

1.3 MTEB 排行深度解读

MTEB 排行的分数需要结合具体任务类型来理解。以下是不同场景下的推荐模型:

应用场景推荐模型理由
通用英文 RAGtext-embedding-3-large英文 Retrieval 得分最高,API 稳定
中文知识库BGE-M3 或 GTE-Qwen2中文场景 MTEB 得分更高,支持本地部署
多语言混合Cohere embed-v3 或 BGE-M3原生多语言设计,跨语言迁移能力强
预算敏感text-embedding-3-small单价仅为 large 的 15%,精度损失可接受
离线/私有化部署BGE-M3 或 GTE-Qwen2-1.5B开源免费,数据不出域
超长文档BGE-M3 或 Jina v38192 Token 支持,减少切分粒度

二、向量检索算法

Embedding 模型将文本编码为向量后,接下来的核心挑战是如何在百万甚至十亿级向量中快速找到最近邻。暴力搜索(Flat)的时间复杂度为 O(n×d),在十亿级数据集上一次查询可能需要数秒,完全不可接受。近似最近邻(ANN)算法通过牺牲少量精度换取数量级的速度提升。

2.1 HNSW(Hierarchical Navigable Small World)

HNSW 是当前综合表现最优的 ANN 算法,几乎所有主流向量数据库都将其作为默认索引方案。

核心原理:构建多层图结构。底层(Layer 0)包含所有向量,每一层向上则按概率采样部分向量,形成越来越稀疏的"高速公路"。检索时从顶层的稀疏图开始,逐层下降定位到目标区域,最终在底层进行精确搜索。

关键参数

参数含义推荐值影响
M每个节点的连接数16–64越大召回率越高,内存占用越大
efConstruction构建时的搜索范围128–256越大构建越慢但索引质量越好
efSearch查询时的搜索范围64–256越大查询越慢但精度越高
import faiss

dimension = 1024
index = faiss.IndexHNSWFlat(dimension, 32)
index.hnsw.efConstruction = 200

import numpy as np
vectors = np.random.random((1_000_000, dimension)).astype("float32")
index.add(vectors)

index.hnsw.efSearch = 128
query = np.random.random((1, dimension)).astype("float32")
distances, indices = index.search(query, k=10)

优劣势:HNSW 的召回率在 95-99% 之间(参数调优后),查询延迟通常在 1-10ms(百万级数据集)。其主要代价是内存占用——每个向量需要额外的图结构开销,约为原始向量大小的 1.5-2 倍。

2.2 IVF(Inverted File Index)

IVF 通过将向量空间聚类来加速检索。首先用 K-Means 将所有向量划分为 nlist 个簇(Voronoi cells),检索时只搜索查询向量最近的 nprobe 个簇内的向量。

核心参数

参数含义推荐值影响
nlist聚类数量√n 到 4√n影响构建时间和搜索范围
nprobe搜索的簇数量1–nlist/10越大精度越高但越慢
100 万向量 → nlist = 1024 → nprobe = 32
搜索范围从 100 万缩小到约 3 万(3%),精度损失约 1-2%

IVF 的优势在于构建速度快支持磁盘存储(IVF_PQ 组合),适合数据量大但内存有限的场景。其劣势是精度上限低于 HNSW,且对数据分布敏感——如果数据分布不均匀,某些簇可能过大导致搜索热点。

2.3 PQ(Product Quantization)

PQ 是一种向量压缩算法,通常与 IVF 组合使用(IVF_PQ)。它将高维向量分割为多个子空间,在每个子空间内用聚类中心代替原始向量,实现大幅压缩。

压缩原理示例

1024 维向量 → 分为 32 个子空间 → 每个子空间 32 维
每个子空间训练 256 个聚类中心(8 bit 量化)
原始:1024 × 4 bytes = 4096 bytes/向量
压缩后:32 × 1 byte = 32 bytes/向量(压缩 128 倍)

优劣势:PQ 将内存占用降低两个数量级,使得十亿级向量可以在单机内存中完成检索。但压缩不可避免地带来精度损失——在 Recall@10 场景下,PQ 的精度通常比 HNSW 低 5-10 个百分点。

2.4 ScaNN(Google)

ScaNN(Scalable Nearest Neighbors)是 Google 开源的 ANN 库,其核心创新在于各向异性量化(Anisotropic Quantization)——在压缩时保留向量在检索方向上的信息,牺牲不重要方向的精度来换取更高的检索准确率。

import scann
import numpy as np

dataset = np.random.random((1_000_000, 128)).astype("float32")

searcher = (
    scann.builder_knn_btree(dataset, 10)
    .tree(
        num_leaves=1000,
        num_leaves_to_search=50,
        training_sample_size=100000
    )
    .score_ah(
        quantization_bits=2,
        rescoreidual_quantization_bits=2
    )
    .reorder(100)
    .build()
)

query = np.random.random((1, 128)).astype("float32")
neighbors, distances = searcher.search(query, k=10)

ScaNN 在 Google 的内部基准测试中,在相同速度下比 FAISS 的 IVF-PQ 精度高 5-10%,适合追求极致性能且愿意接受 Google 生态绑定的场景。

2.5 算法权衡总览

算法召回率查询延迟内存占用构建时间适用数据规模代表实现
Flat100%O(n×d)极快<10 万FAISS IndexFlat
IVF90-98%10 万–1000 万FAISS IndexIVFFlat
HNSW95-99%极快2-3×中等10 万–1 亿FAISS/IndexHNSW、所有主流向量 DB
IVF_PQ85-95%0.1-0.5×中等1 亿–10 亿FAISS IndexIVFPQ
ScaNN92-99%极快0.5-1×中等10 万–1 亿Google ScaNN

实践建议:数据量在百万级以内,HNSW 是无脑首选;超过千万级且内存紧张时,考虑 IVF_PQ;需要极致精度且愿意使用 Google 技术栈时,评估 ScaNN。


三、PGVector 深度分析

3.1 架构与定位

PGVector 是 PostgreSQL 的一个扩展(Extension),在不引入额外基础设施的前提下为 PostgreSQL 增加了向量检索能力。对于已有 PostgreSQL 基础设施的团队,PGVector 是最低成本的向量检索方案——无需运维额外的数据库服务,直接复用现有的 PG 运维体系、备份策略和安全机制

CREATE EXTENSION vector;

CREATE TABLE documents (
    id SERIAL PRIMARY KEY,
    content TEXT NOT NULL,
    embedding vector(1536) NOT NULL,
    metadata JSONB,
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops)
    WITH (m = 16, ef_construction = 200);

3.2 索引类型

PGVector 支持两种主要索引:

IVFFlat

CREATE INDEX ON documents USING ivfflat (embedding vector_l2_ops)
    WITH (lists = 100);
  • 优点:构建速度快,适合数据频繁更新的场景
  • 缺点:需要先有数据才能创建索引(因为需要 K-Means 聚类),新建的空表无法有效使用
  • 限制lists 参数需要在创建时确定,后续修改需要重建索引

HNSW(PGVector 0.5.0+)

CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops)
    WITH (m = 16, ef_construction = 200);

SET hnsw.ef_search = 128;
  • 优点:召回率更高,查询延迟更低
  • 缺点:构建时间较长,内存占用较大
  • 推荐:PGVector 0.5.0 及以上版本优先使用 HNSW

3.3 SQL 集成的独特优势

PGVector 最大的竞争力在于向量检索与关系型查询的无缝融合

SELECT id, content, metadata,
       1 - (embedding <=> '[0.1, 0.2, ...]'::vector) AS similarity
FROM documents
WHERE metadata->>'category' = '技术文档'
  AND metadata->>'year' >= 2024
ORDER BY embedding <=> '[0.1, 0.2, ...]'::vector
LIMIT 10;

这意味着你可以在单条 SQL 语句中完成:元数据过滤 + 向量检索 + 排序 + 分页。在其他向量数据库中,这通常需要多次 API 调用或复杂的过滤管道。

此外,PGVector 可以与 PostgreSQL 的其他扩展组合使用:

  • pg_trgm:实现模糊文本匹配
  • Full-Text Search:实现关键词搜索(支持中文需要 zhparser)
  • Row Level Security:实现细粒度的行级访问控制
  • pg_partman:实现大规模数据的自动分区
-- 混合检索:向量 + 全文搜索的 SQL 实现
SELECT id, content,
       1 - (embedding <=> $1::vector) AS vector_score,
       ts_rank_cd(to_tsvector('chinese', content), plainto_tsquery('chinese', $2)) AS text_score,
       (1 - (embedding <=> $1::vector)) * 0.6 +
       ts_rank_cd(to_tsvector('chinese', content), plainto_tsquery('chinese', $2)) * 0.4 AS combined_score
FROM documents
ORDER BY combined_score DESC
LIMIT 10;

3.4 局限性

局限说明影响
性能天花板单机 PostgreSQL 架构,水平扩展能力有限数据超过 5000 万时查询延迟显著上升
索引类型有限仅支持 IVFFlat 和 HNSW,不支持 PQ 等压缩索引内存占用较大,十亿级数据难以承载
运维耦合向量数据与业务数据共享 PG 实例,大表的 VACUUM/REINDEX 可能影响业务需要精细的资源规划
分布式支持弱Citus 等 PG 分布式方案对向量操作的支持有限大规模场景需要额外的分片策略

3.5 最佳使用场景

PGVector 最适合以下场景:

  1. 已有 PostgreSQL 基础设施:无需引入新组件,开发和运维成本最低
  2. 数据量在百万级以内:在此规模下,PGVector 的 HNSW 索引性能完全满足需求
  3. 强事务需求:需要在同一个数据库事务中完成向量操作和业务数据操作
  4. 多租户隔离:利用 Row Level Security 实现租户级的检索隔离
  5. 原型验证阶段:快速验证 RAG 方案可行性,后续再按需迁移到专用向量数据库

四、Milvus 深度分析

4.1 架构设计

Milvus 是目前功能最完备的开源分布式向量数据库,其架构从设计之初就面向大规模生产场景。Milvus 2.x 采用存算分离架构:

┌──────────────────────────────────────────────────────────┐
│                      Milvus Proxy                        │
│                    (负载均衡 / 路由)                        │
└────────────────────────┬─────────────────────────────────┘
                         │
         ┌───────────────┼───────────────┐
         ▼               ▼               ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ Query Node   │ │ Data Node    │ │ Index Node   │
│ (查询服务)    │ │ (写入服务)    │ │ (索引构建)    │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
       │                │                │
       └────────────────┼────────────────┘
                        ▼
              ┌──────────────────┐
              │  Meta Store      │
              │  (etcd)          │
              └──────────────────┘
                        │
         ┌──────────────┼──────────────┐
         ▼              ▼              ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│  Pulsar/Kafka│ │  MinIO/S3    │ │  etcd        │
│  (日志流)     │  │  (对象存储)   │  │  (元数据)    │
└──────────────┘ └──────────────┘ └──────────────┘

这种架构的每个组件都可以独立水平扩展

  • Query Node 增加可提升查询吞吐
  • Data Node 增加可提升写入吞吐
  • Index Node 增加可加速索引构建
  • 存储层 使用对象存储(MinIO/S3),天然支持弹性扩容

4.2 Collection 与 Partition 模型

Milvus 的数据组织模型:

from pymilvus import MilvusClient, DataType

client = MilvusClient(uri="http://localhost:19530")

schema = MilvusClient.create_schema(auto_id=True, enable_dynamic_field=True)
schema.add_field("id", DataType.INT64, is_primary=True)
schema.add_field("embedding", DataType.FLOAT_VECTOR, dim=1024)
schema.add_field("content", DataType.VARCHAR, max_length=2000)
schema.add_field("source", DataType.VARCHAR, max_length=200)
schema.add_field("category", DataType.VARCHAR, max_length=50)

index_params = client.prepare_index_params()
index_params.add_index(
    field_name="embedding",
    index_type="HNSW",
    metric_type="COSINE",
    params={"M": 16, "efConstruction": 256}
)
index_params.add_index(
    field_name="source",
    index_type="TRIE"
)

client.create_collection(
    collection_name="knowledge_base",
    schema=schema,
    index_params=index_params
)

client.insert(
    collection_name="knowledge_base",
    data=[
        {"embedding": [0.1, 0.2, ...], "content": "...", "source": "产品手册", "category": "技术"},
    ]
)

Partition 允许在同一个 Collection 内按逻辑划分数据。例如按部门、按文档类型分区,检索时可以指定在特定 Partition 中搜索,缩小搜索范围提升精度。

4.3 核心特性

特性说明
混合搜索原生支持向量检索 + 标量过滤的融合查询
多向量字段一个 Collection 可以包含多个向量字段(如稠密 + 稀疏),支持 BGE-M3 等多表示模型
动态字段运行时添加新字段,无需重建 Collection
标量索引支持 Trie、STLsort 等标量索引,加速过滤条件
GPU 索引支持 GPU 加速的 IVF_FLAT、IVF_PQ 索引构建和搜索
多副本支持 Query Node 多副本部署,实现高可用
Time Travel支持按时间点查询历史数据

4.4 Milvus Lite vs Zilliz Cloud

维度Milvus LiteMilvus StandaloneZilliz Cloud
部署方式Python 包内嵌Docker 单机全托管 SaaS
最大数据量约 100 万数千万数十亿
高可用有限(WAL 备份)全面(多副本、自动故障转移)
运维成本中等
适用场景本地开发/测试中小规模生产大规模生产
定价免费免费(自运维)按用量付费
# Milvus Lite:零配置启动
from pymilvus import MilvusClient

client = MilvusClient("milvus_demo.db")
client.create_collection(
    collection_name="test",
    dimension=128
)

client.insert("test", [{"id": i, "vector": [0.1]*128} for i in range(100)])
results = client.search("test", [[0.1]*128], limit=5)

4.5 最佳使用场景

  1. 大规模向量检索:数据量超过千万级,需要水平扩展能力
  2. 多模态检索:图片、视频、文本的统一向量检索
  3. 强过滤需求:需要复杂的标量过滤与向量检索混合查询
  4. 高可用要求:生产环境要求 99.9%+ 的可用性 SLA
  5. 团队有运维能力:能承担 etcd、Pulsar、MinIO 等组件的运维开销

五、Chroma 深度分析

5.1 设计哲学

Chroma 的核心定位是**“最简单的向量数据库”。它将向量存储的核心能力封装为几行 Python 代码即可使用的 API,极大降低了 RAG 系统的搭建门槛。Chroma 不追求极致性能或海量数据支持,而是专注于开发者体验快速原型验证**。

5.2 两种运行模式

嵌入式模式(Embedded Mode)

Chroma 最具特色的使用方式——直接嵌入 Python 进程,无需启动任何服务:

import chromadb

client = chromadb.Client()

collection = client.create_collection(
    name="knowledge_base",
    metadata={"hnsw:space": "cosine"}
)

collection.add(
    documents=[
        "PGVector 是 PostgreSQL 的向量检索扩展",
        "Milvus 是一款开源分布式向量数据库",
        "Chroma 专注于简洁易用的向量存储",
    ],
    ids=["doc1", "doc2", "doc3"],
    metadatas=[
        {"source": "技术文档", "year": 2024},
        {"source": "技术文档", "year": 2024},
        {"source": "技术博客", "year": 2023},
    ]
)

results = collection.query(
    query_texts=["向量数据库选型对比"],
    n_results=2,
    where={"year": {"$gte": 2024}}
)

嵌入式模式的数据存储在本地文件系统中,默认使用 DuckDB + Parquet 作为底层存储引擎。

客户端-服务端模式(Client-Server Mode)

# 启动 Chroma 服务
chroma run --path /data/chroma
import chromadb

client = chromadb.HttpClient(host="localhost", port=8000)
collection = client.get_or_create_collection("knowledge_base")

服务端模式支持多客户端并发访问,适合小型团队共享使用。

5.3 内置 Embedding 支持

Chroma 内置了多种 Embedding 模型的集成,可以自动完成文本到向量的转换:

# 默认使用 Sentence Transformers 的 all-MiniLM-L6-v2
collection = client.create_collection(
    name="auto_embed",
    metadata={"hnsw:space": "cosine"}
)
# 直接传入文本,Chroma 自动向量化
collection.add(documents=["Hello World", "Chroma is simple"])
results = collection.query(query_texts=["greeting"], n_results=1)

5.4 优劣势分析

优势

优势说明
极简 API从安装到首次查询只需 5 行代码
零配置嵌入式模式无需任何配置
内置 Embedding集成 Sentence Transformers,开箱即用
Python 原生与 LangChain、LlamaIndex 等框架深度集成
调试友好可以直接检查 Collection 中的数据和元数据

局限

局限说明影响
数据规模有限实测超过 500 万条向量后性能显著下降不适合大规模生产场景
无分布式支持单机架构,无法水平扩展流量增长时只能垂直升级
高可用缺失嵌入式模式下进程崩溃可能丢失数据生产环境需要定期备份
过滤性能弱标量过滤在大数据量下效率较低复杂过滤条件影响查询延迟
内存管理粗糙大量数据时可能出现内存溢出需要监控内存使用

5.5 最佳使用场景

  1. 快速原型验证:验证 RAG 方案可行性,从想法到可运行 Demo 仅需 30 分钟
  2. 本地开发测试:无需启动 Docker 或远程服务,嵌入式模式随用随停
  3. 教学与学习:向量数据库概念的入门首选
  4. 小型个人项目:数据量在 10 万以内,单用户使用
  5. LangChain/LlamaIndex 快速集成:作为 RAG pipeline 的默认向量存储

六、其他方案速览

6.1 Pinecone

Pinecone 是目前最成熟的全托管向量数据库 SaaS

from pinecone import Pinecone, ServerlessSpec

pc = Pinecone(api_key="your-api-key")
pc.create_index(
    name="knowledge-base",
    dimension=1024,
    metric="cosine",
    spec=ServerlessSpec(cloud="aws", region="us-east-1")
)

index = pc.Index("knowledge-base")
index.upsert(vectors=[
    {"id": "doc1", "values": [0.1]*1024, "metadata": {"source": "产品手册"}}
])

results = index.query(vector=[0.1]*1024, top_k=5, include_metadata=True)

核心优势:Serverless 架构,按查询量计费,零运维;自动扩缩容;内置命名空间实现多租户隔离。

核心劣势:数据锁定(vendor lock-in);大规模场景成本较高;高级过滤能力不如 Milvus。

6.2 Weaviate

Weaviate 的差异化在于内置向量化模块混合搜索原生支持

import weaviate

client = weaviate.connect_to_local()

client.collections.create(
    name="KnowledgeBase",
    vectorizer_config=weaviate.classes.config.Configure.Vectorizer.text2vec_openai(),
    properties=[
        weaviate.classes.config.Property(name="content", data_type=weaviate.classes.config.DataType.TEXT),
        weaviate.classes.config.Property(name="source", data_type=weaviate.classes.config.DataType.TEXT),
    ]
)

collection = client.collections.get("KnowledgeBase")
collection.data.insert({"content": "Weaviate 内置向量化支持", "source": "官方文档"})

results = collection.query.near_text(
    query="向量化数据库",
    limit=5,
    target_vector="default"
)

Weaviate 支持 GraphQL API 查询,以及向量搜索 + BM25 的原生混合搜索(alpha 参数控制权重)。内置的 vectorizer 模块可以在写入时自动调用 OpenAI/ Cohere 等 API 进行向量化。

6.3 Qdrant

Qdrant 使用 Rust 编写,定位为高性能 + 丰富过滤的向量数据库:

from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct, Filter, FieldCondition, MatchValue

client = QdrantClient(url="http://localhost:6333")

client.create_collection(
    collection_name="knowledge_base",
    vectors_config=VectorParams(size=1024, distance=Distance.COSINE),
)

client.upsert(
    collection_name="knowledge_base",
    points=[
        PointStruct(id=1, vector=[0.1]*1024, payload={"source": "文档", "category": "技术"}),
    ]
)

results = client.query_points(
    collection_name="knowledge_base",
    query=[0.1]*1024,
    query_filter=Filter(must=[
        FieldCondition(key="category", match=MatchValue(value="技术"))
    ]),
    limit=5
)

Qdrant 的特色在于其Payload 过滤能力——支持嵌套的 JSON 过滤条件、正则匹配、地理位置过滤等,在需要复杂过滤条件的场景中表现突出。其 Rust 实现带来的低内存占用和高吞吐也是重要优势。

6.4 Weaviate vs Qdrant 对比

维度WeaviateQdrant
实现语言GoRust
核心优势内置向量化、GraphQL、混合搜索高性能、低内存、丰富过滤
向量化内置(自动调用 Embedding API)需要外部向量化
混合搜索原生支持(BM25 + 向量)支持(需手动实现融合)
过滤能力中等(支持基本过滤)强(嵌套过滤、正则、地理位置)
内存效率中等高(Rust 的内存控制优势)
生态集成LangChain、LlamaIndex、HaystackLangChain、LlamaIndex
云服务Weaviate CloudQdrant Cloud
许可证BSD-3-ClauseApache-2.0

七、选型决策表

7.1 多维度对比

维度PGVectorMilvusChromaPineconeWeaviateQdrant
最大数据规模千万级十亿级百万级十亿级亿级亿级
部署复杂度低(PG 扩展)高(多组件)极低零(SaaS)
运维成本低(复用 PG)极低
查询延迟(百万级)5-20ms1-5ms10-50ms5-20ms5-15ms1-5ms
事务支持完整 ACID有限
混合检索SQL 实现原生支持需扩展原生支持原生支持原生支持
多租户隔离Row Level SecurityPartitionCollectionNamespace多种方式Payload 过滤
Embedding 集成需外部需外部内置需外部内置需外部
分布式有限(Citus)原生支持不支持全托管支持支持
生产就绪度
许可证PostgreSQLApache-2.0Apache-2.0商业BSD-3Apache-2.0

7.2 场景化推荐

场景首选方案理由
已有 PostgreSQL,快速搭建PGVector零增量运维,直接复用现有基础设施
千万级以上生产环境Milvus 或 Qdrant分布式架构,水平扩展,高可用
快速原型验证Chroma5 行代码运行,30 分钟搭建 RAG Demo
不想运维任何基础设施Pinecone全托管 SaaS,按量付费
需要内置向量化 + 混合搜索Weaviate一站式解决方案,GraphQL API
高性能 + 复杂过滤QdrantRust 实现,低内存占用,丰富 Payload 过滤
多租户 SaaS 产品Milvus(Partition)或 Qdrant(Payload 过滤)原生多租户隔离能力
数据安全敏感PGVector(自建)或 Milvus(自建)数据不出域,完全自控
成本优先PGVector 或 Chroma无额外基础设施成本

7.3 迁移路径建议

一个务实的演进路径:

Phase 1: Chroma(本地原型)
    ↓ 验证方案可行性
Phase 2: PGVector(轻量生产)
    ↓ 数据量 < 500 万,复用 PG
Phase 3: Milvus/Qdrant(规模增长)
    ↓ 数据量 > 1000 万,需要扩展
Phase 4: Zilliz Cloud/Pinecone(全面托管)
    ↓ 团队转向业务,减少运维

八、安全视角

向量数据库存储的是企业知识的数学表示,其安全性不容忽视。以下从访问控制、加密、审计和租户隔离四个维度展开。

8.1 访问控制

PGVector:Row Level Security

PGVector 继承了 PostgreSQL 的行级安全策略(RLS),可以实现细粒度的数据隔离:

ALTER TABLE documents ENABLE ROW LEVEL SECURITY;

CREATE POLICY tenant_isolation ON documents
    USING (tenant_id = current_setting('app.current_tenant')::int);

CREATE POLICY read_access ON documents
    FOR SELECT
    USING (
        access_level IN ('public', 'internal')
        OR current_user IN (
            SELECT user_name FROM document_permissions
            WHERE document_id = documents.id AND permission = 'read'
        )
    );

SET app.current_tenant = '42';
SELECT * FROM documents;
-- 自动只返回 tenant_id=42 的数据

Milvus:RBAC

Milvus 支持基于角色的访问控制:

from pymilvus import MilvusClient

client = MilvusClient(uri="http://localhost:19530", token="root:Milvus")

client.create_role("reader")
client.grant_privilege(
    role_name="reader",
    object_type="Collection",
    object_name="knowledge_base",
    privilege="Search"
)

client.create_user("analyst", "secure-password")
client.assign_role("analyst", "reader")

Chroma / Qdrant / Weaviate

Chroma 目前不支持任何访问控制,在多用户场景下存在数据泄露风险。Qdrant 和 Weaviate 在云服务版本中提供了 API Key 级别的访问控制和基于 Collection 级别的权限管理。

8.2 静态加密

方案静态加密支持说明
PGVector✅ 原生支持PostgreSQL 的 pgcrypto 扩展 + 磁盘级加密
Milvus✅ 支持依赖底层存储(MinIO 加密、etcd 加密)
Chroma⚠️ 有限需要依赖操作系统级磁盘加密
Pinecone✅ 全托管AWS KMS / GCP Cloud KMS 加密
Weaviate Cloud✅ 全托管云平台原生加密
Qdrant Cloud✅ 全托管云平台原生加密

对于自建方案,建议使用 磁盘级加密(如 LUKS、FileVault)配合 传输层加密(TLS/SSL)实现全链路加密。

8.3 审计日志

生产环境需要记录向量数据库的关键操作日志:

  • 查询审计:谁在什么时间查询了什么内容——对于合规要求(如 GDPR、等保)至关重要
  • 写入审计:谁修改或删除了向量数据
  • 索引操作:索引的创建、重建、删除记录

PGVector 可以利用 PostgreSQL 原生的 pgAudit 扩展实现细粒度审计:

CREATE EXTENSION pgaudit;

SET pgaudit.log = 'read, write, ddl';
SET pgaudit.log_catalog = on;
SET pgaudit.log_level = 'log';

Milvus 可以通过其审计日志功能和底层 Kafka/Pulsar 的消息日志实现操作审计。

8.4 租户隔离

多租户场景下,向量数据库的隔离策略直接影响安全性和性能:

隔离级别实现方式安全性性能影响代表方案
物理隔离每租户独立实例最高Milvus 多实例
Collection 级隔离每租户独立 CollectionMilvus/PGVector
Partition 级隔离同 Collection 不同 PartitionMilvus
行级隔离同表,过滤条件隔离中(过滤开销)PGVector RLS
Payload 过滤同 Collection,按 Payload 过滤Qdrant
Namespace 隔离逻辑命名空间隔离Pinecone

实践建议:租户数量少(<100)时使用 Collection 级隔离,租户数量多时使用行级/Payload 过滤。对于安全要求极高的租户,考虑物理隔离。


九、延伸阅读

核心论文

向量数据库官方文档

基准测试与评测

实践资源


Embedding 模型和向量数据库的选型并非一次性的决策——随着数据规模增长、业务需求变化和技术栈演进,今天最优的选择可能在六个月后需要调整。建议团队遵循"从简入繁"的原则:先用 Chroma 或 PGVector 快速验证方案,待数据量和业务复杂度增长后再按需迁移到 Milvus 或托管服务。在整个过程中,建立可量化的评测体系来驱动选型决策,远比盲目追求"最先进的技术"更为重要。