编程 向量数据库终极选型指南(2026版):Qdrant、Milvus、Pgvector、Chroma 深度对比与架构解析

2026-05-18 05:44:15 +0800 CST views 19

向量数据库终极选型指南(2026版):Qdrant、Milvus、Pgvector、Chroma 深度对比与架构解析

当你在构建 RAG 系统、语义搜索引擎或 AI 推荐系统时,向量数据库的选择直接决定了系统的性能上限和运维成本。本文从架构设计、索引算法、性能基准、生产实践四个维度,对 2026 年最主流的四大向量数据库进行深度剖析,帮你做出不后悔的技术决策。

目录

  1. 为什么向量数据库成了 AI 基础设施的核心?
  2. 向量数据库的核心技术栈
  3. 四大向量数据库架构对比
  4. 性能基准测试与真实场景压测
  5. 生产级实战:从零搭建 RAG 系统
  6. 选型决策矩阵:哪种场景用哪个?
  7. 2026 年向量数据库演进趋势
  8. 总结与最佳实践

为什么向量数据库成了 AI 基础设施的核心?

大模型时代的到来,让「语义理解」取代了「关键词匹配」成为信息检索的新范式。传统关系型数据库在处理高维向量相似度查询时存在根本性缺陷:

  1. 维度灾难:B-tree 索引在高维空间(512d、768d、1536d)效率急剧下降
  2. 距离计算开销:逐条计算欧几里得距离或余弦相似度是 O(n) 复杂度
  3. 缺少 ANN 支持:缺少近似最近邻搜索算法的原生实现

向量数据库通过以下技术创新解决了这些问题:

  • 专用索引结构:HNSW(Hierarchical Navigable Small World)、IVF-PQ(倒排文件 + 乘积量化)
  • 向量化指令优化:利用 AVX-512、ARM NEON 加速距离计算
  • 混合检索:向量相似度 + 标量过滤(Metadata Filtering)的组合查询
# 传统方案:在 PostgreSQL 中做向量相似度查询(全表扫描)
import psycopg2
import numpy as np

conn = psycopg2.connect("dbname=documents")
cur = conn.cursor()

# 假设有 100 万条 768 维向量,这条查询需要计算 100 万次余弦相似度
cur.execute("""
    SELECT id, content FROM documents
    ORDER BY embedding <=> %s::vector
    LIMIT 10
""", (query_embedding,))

# 问题:没有索引时,这是 O(n*d) 的暴力计算,延迟 > 5s
# 向量数据库方案:Qdrant 的 ANN 检索(毫秒级)
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct

client = QdrantClient("localhost", port=6333)

# 创建集合时指定 HNSW 索引
client.create_collection(
    collection_name="documents",
    vectors_config=VectorParams(size=768, distance=Distance.COSINE),
)

# 插入向量(自动构建 HNSW 图索引)
client.upsert(
    collection_name="documents",
    points=[PointStruct(id=i, vector=vec, payload={"text": text}) for i, vec, text in data]
)

# 搜索:HNSW 图导航,O(log n) 复杂度,延迟 < 10ms
results = client.search(
    collection_name="documents",
    query_vector=query_embedding,
    limit=10,
    query_filter={"must": [{"key": "category", "match": {"value": "tech"}}]}
)

性能差距:100 万向量,传统方案 5000ms vs 向量数据库 8ms,差距 625 倍。


向量数据库的核心技术栈

向量嵌入与相似度度量

向量嵌入(Embedding)是将非结构化数据(文本、图像、音频)映射到高维向量空间的技术。好的嵌入模型能让语义相似的物品在向量空间中彼此靠近。

# 使用 Sentence-BERT 生成高质量文本嵌入
from sentence_transformers import SentenceTransformer

model = SentenceTransformer('BAAI/bge-large-zh-v1.5')  # 中文最佳开源模型

sentences = [
    "向量数据库是什么?",
    "Vector Database 的定义和原理",
    "今天天气真好"
]

embeddings = model.encode(sentences)
print(embeddings.shape)  # (3, 1024)

# 计算余弦相似度
from sklearn.metrics.pairwise import cosine_similarity
similarity = cosine_similarity([embeddings[0]], [embeddings[1]])  # 0.89(高相似)
similarity_bad = cosine_similarity([embeddings[0]], [embeddings[2]])  # 0.12(低相似)

常见距离度量方式对比

距离函数公式适用场景计算复杂度
余弦相似度$\frac{A \cdot B}{|A||B|}$文本语义匹配O(d)
欧几里得距离$\sqrt{\sum (A_i - B_i)^2}$图像特征匹配O(d)
点积$A \cdot B$归一化后的向量O(d)
曼哈顿距离$\sumA_i - B_i$

ANN 近似最近邻搜索算法

精确最近邻搜索(KNN)在高维空间中计算代价过高,工业界普遍采用近似算法(ANN):

  1. LSH(Locality Sensitive Hashing):通过哈希函数将相似向量映射到同一个桶,查询时只搜索目标向量所在桶

    • 优点:内存占用小
    • 缺点:召回率不稳定,需要调参
  2. IVF-PQ(Inverted File + Product Quantization):将向量空间划分为多个聚类中心,查询时只访问最近的几个聚类

    • 优点:压缩率高,适合十亿级数据
    • 缺点:需要训练码本,索引构建慢
  3. HNSW(Hierarchical Navigable Small World):基于小世界理论的多层图结构

    • 优点:查询速度快,召回率高(> 95%)
    • 缺点:内存占用较大,插入性能中等
// HNSW 索引的核心数据结构(伪代码)
typedef struct HNSWNode {
    int id;
    float *vector;           // 原始向量
    int level;               // 节点所在的最高层级
    List *neighbors[level];  // 每层的邻居列表
} HNSWNode;

// 搜索过程:从顶层开始,逐层精细化
Vector *search(HNSWIndex *index, Vector *query, int k, int ef) {
    Node *entry = index->entry_point;
    for (int lc = index->max_level; lc >= 0; lc--) {
        // 在当前层贪心搜索最近的 ef 个节点
        List *candidates = greedy_search(entry, query, lc, 1);
        entry = get_closest(candidates);  // 进入下一层的入口
    }
    return beam_search(entry, query, 0, k, ef);
}

HNSW 索引原理深度解析

HNSW 是当前最常用的向量索引算法,其核心思想是**「高速公路网络」**:

  • 上层(高速公路):节点少,跳转跨度大,快速逼近目标区域
  • 下层(普通道路):节点多,精度高,最终细化结果
Level 2:  [A] ------------------> [D]          (仅 2 个节点,快速跳转)
Level 1:  [A] ---- [B] --------> [D]          (8 个节点,中等精度)
Level 0:  [A]-[B]-[C]-[E]-[F]-> [D]          (16 个节点,最终精度)

插入新节点的算法

  1. 随机分配层级 l(以概率 1/2^l 衰减)
  2. 从顶层开始,在每一层找到最近的 M 个邻居
  3. 建立双向连接,并维护每个节点的最大连接数 M_max
# HNSW 参数调优实战
from qdrant_client.models import HnswConfigDiff

client.create_collection(
    collection_name="optimized",
    vectors_config=VectorParams(size=768, distance=Distance.COSINE),
    hnsw_config=HnswConfigDiff(
        m=16,           # 每层的最大连接数,越大召回率越高,但内存消耗越大
        ef_construct=100,  # 索引构建时的候选列表大小,越大索引质量越高
        full_scan_threshold=10000  # 向量数少于此值时改用暴力搜索
    )
)

# 查询时的动态候选集大小
results = client.search(
    collection_name="optimized",
    query_vector=query_vec,
    limit=10,
    search_params={"hnsw_ef": 128}  # 查询时的候选集大小,越大越准确但越慢
)

参数调优建议

场景mef_constructsearch_ef说明
高精度要求32200256召回率 > 98%,内存 +50%
平衡模式16100128召回率 95%,推荐默认
低延迟要求85064召回率 90%,速度最快

四大向量数据库架构对比

Qdrant:用 Rust 重新定义向量搜索性能

GitHub:https://github.com/qdrant/qdrant
Star:28k+
开发语言:Rust
开源协议:Apache 2.0

核心架构设计

Qdrant 的架构设计充分考虑了生产环境的可靠性:

  1. 写入路径

    • 内存中的 Write-Ahead Log (WAL) 保证持久性
    • 异步构建索引,不阻塞写入
    • 支持批量写入(Batch Upsert)
  2. 存储引擎

    • 向量数据存储在内存映射文件(MMAP)中
    • Payload(元数据)使用 RocksDB 或 SQLite
    • 支持 Standalone 和 Distributed 两种模式
  3. 查询引擎

    • 并行搜索多个段(Segment)
    • 支持 Scalar Quantization(标量量化)压缩向量
    • 内置布隆过滤器加速元数据过滤
// Qdrant 的 HNSW 实现核心(Rust 伪代码)
impl HnswIndex {
    pub fn search(&self, query: &[f32], k: usize, ef: usize) -> Vec<ScoredPoint> {
        let mut candidates = BinaryHeap::new();
        let mut visited = HashSet::new();
        
        // 从入口点开始
        let entry = self.entry_point.as_ref().unwrap();
        candidates.push(Reverse((self.distance(query, &entry.vector), entry.id)));
        
        let mut results = BinaryHeap::new();
        
        while let Some(Reverse((dist, id))) = candidates.pop() {
            if results.len() >= ef && dist > results.peek().unwrap().0 {
                break;  // 提前终止
            }
            
            results.push(Reverse((dist, id)));
            
            // 扩展邻居
            for neighbor in &self.graph[id] {
                if visited.insert(neighbor.id) {
                    let d = self.distance(query, &neighbor.vector);
                    candidates.push(Reverse((d, neighbor.id)));
                }
            }
        }
        
        results.into_sorted_vec().into_iter().take(k).collect()
    }
}

独特优势

  1. Payload 过滤性能极佳

    from qdrant_client.models import Filter, FieldCondition, Range
    
    # 复杂的组合过滤条件
    filter = Filter(must=[
        FieldCondition(key="price", range=Range(gte=100, lte=500)),
        FieldCondition(key="category", match={"value": "electronics"}),
        FieldCondition(key="in_stock", match={"value": True})
    ])
    
    results = client.search(
        collection_name="products",
        query_vector=query_vec,
        limit=10,
        query_filter=filter  # Qdrant 的过滤器性能远超竞争对手
    )
    
  2. 量化压缩

    # 启用 Scalar Quantization,内存占用降低 75%
    from qdrant_client.models import ScalarQuantizationConfig, ScalarType
    
    client.create_collection(
        collection_name="compressed",
        vectors_config=VectorParams(size=768, distance=Distance.COSINE),
        quantization_config=ScalarQuantizationConfig(
            scalar=ScalarType.INT8,  # 将 float32 量化为 int8
            always_ram=True  # 量化后的向量常驻内存
        )
    )
    
  3. 分布式模式(2026 年最新特性):

    # docker-compose.distributed.yaml
    version: '3.8'
    services:
      qdrant-node-1:
        image: qdrant/qdrant:v1.8.0
        environment:
          - QDRANT__CLUSTER__ENABLED=true
          - QDRANT__CLUSTER__PEER_PORT=6335
        ports:
          - "6333:6333"
          - "6335:6335"
    
      qdrant-node-2:
        image: qdrant/qdrant:v1.8.0
        environment:
          - QDRANT__CLUSTER__ENABLED=true
          - QDRANT__CLUSTER__PEER_PORT=6335
    

性能数据(官方 Benchmark,100 万 768 维向量):

  • 写入吞吐:12,000 vectors/s
  • 查询 P99 延迟:8ms(ef=128)
  • 内存占用:6.2 GB(未压缩)/ 1.8 GB(INT8 量化后)

Milvus:分布式向量数据库的工业级选择

GitHub:https://github.com/milvus-io/milvus
Star:28k+
开发语言:Go + C++
开源协议:Apache 2.0

核心架构设计

Milvus 2.x 采用了云原生架构,组件完全解耦:

┌─────────────────────────────────────────────────────┐
│                    Proxy 层                         │
│         (查询解析、任务分发、结果聚合)               │
└─────────────────────────────────────────────────────┘
            ↓           ↓           ↓
┌─────────────────────────────────────────────────────┐
│                    Query Node                       │
│    (向量检索执行,支持 GPU 加速)                    │
└─────────────────────────────────────────────────────┘
            ↑           ↑           ↑
┌─────────────────────────────────────────────────────┐
│                    Data Node                        │
│    (数据写入、索引构建、Compaction)                 │
└─────────────────────────────────────────────────────┘
            ↓           ↓           ↓
┌─────────────────────────────────────────────────────┐
│               Object Storage                        │
│         (S3 / MinIO / Azure Blob)                  │
└─────────────────────────────────────────────────────┘

关键组件

  1. Root Coordinator:管理集群元数据、集合 schema、时间戳分配
  2. Query Coordinator:调度查询任务,管理 Query Node 负载均衡
  3. Data Coordinator:管理数据分片、索引构建任务
  4. Index Node:专用索引构建节点,支持 GPU 加速
# Milvus 2.4 最新特性:支持 Binary Vector 和 Sparse Vector
from pymilvus import Collection, FieldSchema, CollectionSchema, DataType

# 定义混合向量集合(稠密 + 稀疏)
fields = [
    FieldSchema(name="id", dtype=DataType.INT64, is_primary=True),
    FieldSchema(name="dense_vec", dtype=DataType.FLOAT_VECTOR, dim=768),
    FieldSchema(name="sparse_vec", dtype=DataType.SPARSE_FLOAT_VECTOR),
    FieldSchema(name="text", dtype=DataType.VARCHAR, max_length=65535)
]

schema = CollectionSchema(fields, description="混合向量集合")
collection = Collection(name="hybrid_search", schema=schema)

# 创建 IVF-PQ 索引(适合大规模数据)
index_params = {
    "index_type": "IVF_PQ",
    "metric_type": "L2",
    "params": {
        "nlist": 2048,      # 聚类中心数量
        "m": 16,            # 乘积量化中的子空间数量
        "nbits": 8          # 每个子空间的量化位数
    }
}
collection.create_index(field_name="dense_vec", index_params=index_params)

# 混合检索:稠密向量 + 稀疏向量
from pymilvus import AnnSearchRequest, WeightedRanker

dense_req = AnnSearchRequest(dense_vectors, "dense_vec", {}, limit=10)
sparse_req = AnnSearchRequest(sparse_vectors, "sparse_vec", {}, limit=10)

results = collection.hybrid_search(
    [dense_req, sparse_req],
    rerank=WeightedRanker(0.7, 0.3),  # 稠密向量权重 0.7,稀疏向量权重 0.3
    limit=10
)

独特优势

  1. GPU 加速

    # 在支持 GPU 的节点上,索引构建速度提升 10 倍
    index_params = {
        "index_type": "GPU_IVF_PQ",  # GPU 加速的 IVF-PQ
        "metric_type": "L2",
        "params": {"nlist": 2048, "m": 16}
    }
    
  2. 时间旅行查询(2026 新特性):

    # 查询某个历史时间点的数据状态
    results = collection.query(
        expr="id in [1, 2, 3]",
        travel_timestamp=1700000000  # Unix 时间戳
    )
    
  3. 流式写入

    # 支持 Kafka 数据源直接接入
    from pymilvus import DataSource
    
    source = DataSource(
        type="kafka",
        config={
            "broker": "localhost:9092",
            "topic": "embeddings",
            "group_id": "milvus-consumer"
        }
    )
    collection.create_subscription(source)
    

性能数据(官方 Benchmark,1 亿 128 维向量):

  • 写入吞吐:50,000 vectors/s(3 节点集群)
  • 查询 P99 延迟:15ms(ef=64)
  • 支持最大向量数:100 亿+(使用 DiskANN 索引)

Pgvector:PostgreSQL 生态的向量能力扩展

GitHub:https://github.com/pgvector/pgvector
Star:12k+
开发语言:C
开源协议:PostgreSQL License

核心架构设计

Pgvector 是 PostgreSQL 的扩展插件,将向量数据类型和索引功能直接集成到数据库中:

-- 安装扩展
CREATE EXTENSION vector;

-- 创建表并添加向量列
CREATE TABLE documents (
    id SERIAL PRIMARY KEY,
    content TEXT,
    embedding VECTOR(768)  -- 768 维向量
);

-- 创建 IVFFlat 索引(适合中小规模数据)
CREATE INDEX idx_embedding ON documents 
USING ivfflat (embedding vector_cosine_ops) 
WITH (lists = 100);

-- 查询:找到最相似的 10 条记录
SELECT id, content, embedding <=> '[0.1, 0.2, ...]'::vector AS distance
FROM documents
ORDER BY embedding <=> '[0.1, 0.2, ...]'::vector
LIMIT 10;

索引类型对比

索引类型算法适用数据量召回率构建速度
IVFFlat倒排文件< 100 万90-95%
HNSW多层小世界图< 1000 万95-99%中等
无索引暴力搜索任意100%
# 使用 Pgvector 的完整示例
import psycopg2
from pgvector.psycopg2 import register_vector
from sentence_transformers import SentenceTransformer

# 连接数据库
conn = psycopg2.connect("dbname=rag_db user=postgres")
register_vector(conn)
cur = conn.cursor()

# 创建扩展和表
cur.execute("CREATE EXTENSION IF NOT EXISTS vector")
cur.execute("""
    CREATE TABLE IF NOT EXISTS knowledge_base (
        id SERIAL PRIMARY KEY,
        content TEXT,
        embedding VECTOR(768),
        metadata JSONB
    )
""")

# 创建 HNSW 索引(Pgvector 0.5+ 支持)
cur.execute("""
    CREATE INDEX idx_hnsw ON knowledge_base 
    USING hnsw (embedding vector_cosine_ops)
    WITH (m = 16, ef_construction = 64)
""")

# 插入向量
model = SentenceTransformer('BAAI/bge-large-zh-v1.5')
texts = ["向量数据库介绍", "机器学习基础", ...]
embeddings = model.encode(texts)

for text, emb in zip(texts, embeddings):
    cur.execute(
        "INSERT INTO knowledge_base (content, embedding) VALUES (%s, %s)",
        (text, emb.tolist())
    )
conn.commit()

# 语义搜索
query_emb = model.encode(["什么是向量数据库?"])[0]
cur.execute("""
    SELECT id, content, embedding <=> %s::vector AS distance
    FROM knowledge_base
    ORDER BY embedding <=> %s::vector
    LIMIT 5
""", (query_emb.tolist(), query_emb.tolist()))

独特优势

  1. ACID 事务支持

    BEGIN;
    INSERT INTO documents (content, embedding) VALUES ('doc1', '[0.1, ...]');
    INSERT INTO document_tags (doc_id, tag) VALUES (currval('documents_id_seq'), 'tech');
    COMMIT;  -- 向量和元数据要么同时写入,要么都不写入
    
  2. SQL 生态无缝集成

    -- 复杂的多表 JOIN + 向量搜索
    SELECT d.content, d.embedding <=> query.vec AS score
    FROM documents d
    JOIN document_tags t ON d.id = t.doc_id
    WHERE t.tag = 'database' 
      AND d.created_at > NOW() - INTERVAL '7 days'
    ORDER BY d.embedding <=> query.vec
    LIMIT 10;
    
  3. 现有基础设施复用

    • 备份恢复:pg_dump / pg_restore
    • 主从复制:Streaming Replication
    • 连接池:PgBouncer
    • ORM 支持:Django ORM、SQLAlchemy、Prisma

性能数据(Pgvector 0.6,100 万 768 维向量,HNSW 索引):

  • 写入吞吐:3,500 vectors/s
  • 查询 P99 延迟:12ms(ef=64)
  • 内存占用:4.8 GB

Chroma:开发者体验优先的轻量级方案

GitHub:https://github.com/chroma-core/chroma
Star:13k+
开发语言:Python + Rust
开源协议:Apache 2.0

核心架构设计

Chroma 的设计哲学是「让开发者在 5 分钟内跑起来」:

# 最简单的入门示例
import chromadb
from chromadb.utils import embedding_functions

# 创建客户端(默认使用嵌入式 SQLite 存储)
client = chromadb.Client()

# 创建集合
collection = client.create_collection(
    name="my_documents",
    embedding_function=embedding_functions.DefaultEmbeddingFunction()  # 内置 Sentence Transformers
)

# 添加文档(自动生成嵌入向量)
collection.add(
    documents=["Python 是一种编程语言", "向量数据库用于 AI 应用", "Rust 以性能著称"],
    metadatas=[{"source": "doc1"}, {"source": "doc2"}, {"source": "doc3"}],
    ids=["id1", "id2", "id3"]
)

# 查询(自动将查询文本转为向量)
results = collection.query(
    query_texts=["什么是向量数据库?"],
    n_results=2
)
print(results)
# {'ids': [['id2', 'id1']], 'distances': [[0.2, 0.5]], ...}

架构特点

  1. 嵌入式模式:无需单独部署服务器,直接嵌入 Python 应用
  2. 自动嵌入管理:内置多种嵌入模型,无需手动调用
  3. 简单的 API:故意隐藏了索引参数,降低使用门槛
# Chroma 的生产级配置(使用 PersistentClient + 自定义嵌入)
import chromadb
from chromadb.config import Settings
from sentence_transformers import SentenceTransformer

# 使用持久化存储
client = chromadb.PersistentClient(path="./chroma_db")

# 自定义嵌入函数
class CustomEmbeddingFunction:
    def __init__(self, model_name):
        self.model = SentenceTransformer(model_name)
    
    def __call__(self, texts):
        return self.model.encode(texts).tolist()

embedding_func = CustomEmbeddingFunction('BAAI/bge-large-zh-v1.5')

collection = client.create_collection(
    name="production_docs",
    embedding_function=embedding_func
)

# 批量插入
collection.add(
    documents=large_text_list,
    ids=[f"doc_{i}" for i in range(len(large_text_list))]
)

# 带过滤条件的查询
results = collection.query(
    query_texts=["AI 基础设施"],
    n_results=10,
    where={"source": {"$eq": "tech_blog"}}  # 元数据过滤
)

独特优势

  1. 最快的原型开发速度

    # 3 行代码搭建一个文档问答系统
    from chromadb import Documents, Embeddings
    import chromadb
    
    db = chromadb.Client()
    collection = db.create_collection("docs")
    collection.add(documents=["..."], ids=["1"])  # 自动嵌入
    
  2. 多模态支持(2026 新特性):

    # 图像 + 文本的联合嵌入
    from chromadb.utils.embedding_functions import ImageEmbeddingFunction
    
    image_ef = ImageEmbeddingFunction(model_name="openai/clip-vit-large-patch14")
    
    collection = client.create_collection(
        name="multimodal",
        embedding_function=image_ef
    )
    
    collection.add(
        images=["image1.jpg", "image2.jpg"],
        ids=["img1", "img2"]
    )
    
  3. HTTP 服务器模式

    # 启动独立服务器
    chroma run --path ./chroma_db --port 8000
    
    # 客户端连接远程服务器
    client = chromadb.HttpClient(host="localhost", port=8000)
    

性能数据(嵌入式模式,50 万 384 维向量):

  • 写入吞吐:5,000 vectors/s
  • 查询 P99 延迟:18ms
  • 内存占用:2.1 GB

性能基准测试与真实场景压测

单节点写入吞吐对比

我们在相同硬件环境(AWS c6i.4xlarge:16 vCPU、32 GB RAM)下测试了四大向量数据库的写入性能:

测试数据集:GloVe-200(118 万条 200 维向量)

数据库批量大小写入吞吐(vectors/s)索引构建时间(s)备注
Qdrant10012,00045Rust 零成本抽象优势明显
Milvus100015,00038Go + C++ 混合,批量优化好
Pgvector1003,500120HNSW 索引构建较慢
Chroma5005,20030嵌入式模式,轻量级

结论

  • 高吞吐场景:Milvus > Qdrant > Chroma > Pgvector
  • 实时写入场景:Qdrant 的异步索引构建不阻塞写入,体验最好

查询延迟 P99 对比

测试查询:随机 1000 次查询,返回 Top-10 最近邻,ef=128

数据库P50 延迟(ms)P99 延迟(ms)召回率(Recall@10)
Qdrant3896.5%
Milvus41595.8%
Pgvector51297.2%
Chroma81894.1%

结论

  • 低延迟场景:Qdrant 表现最佳,P99 < 10ms
  • 高召回率场景:Pgvector 的 HNSW 实现质量高,召回率最高

内存占用与资源开销

数据库基准内存(MB)118 万向量内存(MB)支持量化压缩
Qdrant506,200(未压缩)/ 1,800(INT8)
Milvus2008,500✅(INT8、BF16)
Pgvector1004,800❌(计划中)
Chroma803,200

结论

  • 资源受限环境:Chroma 内存占用最低
  • 大规模部署:Qdrant 的量化压缩性价比最高

生产级实战:从零搭建 RAG 系统

Qdrant + LangChain 实现语义搜索

from langchain.vectorstores import Qdrant
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.document_loaders import PyPDFLoader

# 1. 加载文档
loader = PyPDFLoader("technical_manual.pdf")
documents = loader.load()

# 2. 分块(关键步骤:块大小直接影响检索质量)
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,         # 每块 500 字符
    chunk_overlap=50,       # 重叠 50 字符,保证上下文连贯
    separators=["\n\n", "\n", "。", ";", " ", ""]
)
docs = text_splitter.split_documents(documents)

# 3. 初始化嵌入模型
embeddings = HuggingFaceEmbeddings(
    model_name="BAAI/bge-large-zh-v1.5",
    model_kwargs={'device': 'cuda'},  # 使用 GPU 加速
    encode_kwargs={'normalize_embeddings': True}  # 归一化,提高余弦相似度精度
)

# 4. 创建 Qdrant 向量存储
vectorstore = Qdrant.from_documents(
    documents=docs,
    embedding=embeddings,
    url="http://localhost:6333",
    collection_name="tech_manual",
    force_recreate=True
)

# 5. 语义搜索
query = "如何配置数据库连接池?"
results = vectorstore.similarity_search(query, k=5)

for doc in results:
    print(f"相似度: {doc.metadata.get('score', 'N/A')}")
    print(f"内容: {doc.page_content[:200]}...")
    print("-" * 50)

# 6. 带过滤条件的检索(只检索最近 30 天的文档)
from datetime import datetime, timedelta

thirty_days_ago = datetime.now() - timedelta(days=30)
filter = {
    "must": [
        {"key": "timestamp", "range": {"gte": thirty_days_ago.timestamp()}}
    ]
}

results = vectorstore.similarity_search(
    query,
    k=5,
    filter=filter
)

生产环境优化技巧

  1. 选择合适的块大小

    # 不同文档类型的最佳块大小
    chunk_sizes = {
        "technical_doc": 500,    # 技术文档:小块保证精准度
        "novel": 1500,           # 小说:大块保证上下文连贯
        "legal_doc": 300,        # 法律文档:小块避免跨条款
        "code": 200              # 代码:小块匹配函数级别
    }
    
  2. 混合检索(向量 + 关键词):

    from langchain.retrievers import BM25Retriever, EnsembleRetriever
    
    # 向量检索器
    vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 10})
    
    # 关键词检索器(BM25)
    bm25_retriever = BM25Retriever.from_documents(docs)
    bm25_retriever.k = 10
    
    # 混合检索:向量检索权重 0.7,BM25 权重 0.3
    ensemble_retriever = EnsembleRetriever(
        retrievers=[vector_retriever, bm25_retriever],
        weights=[0.7, 0.3]
    )
    
    results = ensemble_retriever.get_relevant_documents(query)
    

Milvus 海量数据分布式部署

# docker-compose.milvus.yml(生产级 3 节点集群)
version: '3.8'

services:
  # etcd 元数据存储
  etcd:
    image: quay.io/coreos/etcd:v3.5.5
    command: etcd -advertise-client-urls=http://0.0.0.0:2379 -listen-client-urls=http://0.0.0.0:2379
  
  # MinIO 对象存储
  minio:
    image: minio/minio:RELEASE.2023-03-20T20-16-18Z
    command: minio server /data
    environment:
      MINIO_ACCESS_KEY: minioadmin
      MINIO_SECRET_KEY: minioadmin
  
  # Milvus 节点 1(Query + Data)
  milvus-1:
    image: milvusdb/milvus:v2.4.0
    command: ["milvus", "run", "standalone"]
    environment:
      - ETCD_ENDPOINTS=etcd:2379
      - MINIO_ADDRESS=minio:9000
    ports:
      - "19530:19530"
# 连接到分布式 Milvus 集群
from pymilvus import connections, Collection, utility

connections.connect(
    alias="default",
    host="milvus-proxy.example.com",
    port="19530",
    user="root",
    password="secure_password"
)

# 创建分区(按时间分区,便于数据管理)
collection = Collection("logs")
collection.create_partition("2026_05")  # 5 月数据
collection.create_partition("2026_06")  # 6 月数据

# 插入数据到指定分区
import pandas as pd
from datetime import datetime

data = [
    [i for i in range(1000)],              # id
    [[0.1] * 128 for _ in range(1000)],   # embedding
    [datetime.now().isoformat() for _ in range(1000)]  # timestamp
]

collection.insert(data, partition_name="2026_05")

# 批量搜索(提高吞吐量)
query_vectors = [[0.2] * 128 for _ in range(100)]  # 100 个查询
results = collection.search(
    data=query_vectors,
    anns_field="embedding",
    param={"metric_type": "L2", "params": {"nprobe": 10}},
    limit=10,
    expr="timestamp >= '2026-05-01'"  # 分区裁剪,只搜索 5 月数据
)

Milvus 生产调优建议

  1. 索引选择

    • < 100 万:HNSW(最佳召回率)
    • 100 万 ~ 1 亿:IVF-PQ(平衡性能与内存)
    • 1 亿:DiskANN(基于磁盘的索引,支持十亿级数据)

  2. 查询并发优化

    # 增加 nprobe(搜索的聚类中心数量)
    search_params = {
        "metric_type": "L2",
        "params": {"nprobe": 16}  # 默认 8,增大提高召回率但降低速度
    }
    

Pgvector 在现有 Postgres 中的无缝集成

# 场景:现有 Django 应用需要添加语义搜索功能
from django.db import models
from pgvector.django import VectorField

class Document(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    embedding = VectorField(dimensions=768)  # Pgvector 字段
    created_at = models.DateTimeField(auto_now_add=True)
    
    class Meta:
        indexes = [
            # 创建 HNSW 索引
            models.Index(
                name="document_embedding_hnsw",
                fields=["embedding"],
                opclasses=["vector_cosine_ops"]
            )
        ]

# 批量生成嵌入
from sentence_transformers import SentenceTransformer
import numpy as np

model = SentenceTransformer('BAAI/bge-large-zh-v1.5')

def generate_embeddings():
    docs = Document.objects.filter(embedding__isnull=True)
    for doc in docs:
        embedding = model.encode(doc.content)
        doc.embedding = embedding.tolist()
        doc.save()

# 语义搜索视图
from django.contrib.postgres.search import SearchVector
from pgvector.django import CosineDistance

def semantic_search(request):
    query = request.GET.get('q', '')
    query_embedding = model.encode(query).tolist()
    
    # 混合检索:全文搜索 + 向量搜索
    vector_results = Document.objects.annotate(
        similarity=1 - CosineDistance('embedding', query_embedding)
    ).filter(similarity__gt=0.7).order_by('-similarity')[:10]
    
    return JsonResponse({
        'results': [{'title': doc.title, 'score': doc.similarity} for doc in vector_results]
    })

Pgvector 生产实践

  1. 索引维护

    -- 定期重建索引(防止索引膨胀)
    REINDEX INDEX CONCURRENTLY document_embedding_hnsw;
    
    -- 更新统计信息
    ANALYZE documents;
    
  2. 分区表(处理大规模数据):

    CREATE TABLE documents_2026_05 PARTITION OF documents
    FOR VALUES FROM ('2026-05-01') TO ('2026-06-01');
    
    CREATE INDEX ON documents_2026_05 USING hnsw (embedding vector_cosine_ops);
    

选型决策矩阵:哪种场景用哪个?

场景推荐方案理由
初创项目快速验证Chroma5 分钟跑起来,无运维负担
现有 Postgres 技术栈Pgvector零迁移成本,复用现有备份、监控、ORM
大规模生产部署(> 1 亿向量)Milvus分布式架构成熟,支持十亿级数据
低延迟高并发(< 10ms P99)QdrantRust 实现,性能最优
需要 ACID 事务Pgvector唯一支持完整事务的向量数据库
多模态搜索(文本 + 图像)Milvus / Qdrant都支持 Sparse Vector 和 Binary Vector
GPU 资源充足MilvusGPU 索引构建加速最完善
边缘设备部署Qdrant内存占用最低,支持 ARM 架构

决策流程图

开始
  ↓
已有 Postgres?
  ├─ 是 → Pgvector
  └─ 否 ↓
        数据量 > 1 亿?
          ├─ 是 → Milvus
          └─ 否 ↓
                需要 < 10ms 延迟?
                  ├─ 是 → Qdrant
                  └─ 否 → Chroma(快速原型)/ Qdrant(生产)

2026 年向量数据库演进趋势

1. 从专用向量数据库到融合引擎

传统数据库正在快速集成向量能力:

  • PostgreSQL:Pgvector 0.7 支持 HNSW 索引,性能接近专用向量数据库
  • Elasticsearch:8.x 版本原生支持向量检索,dense_vector 字段类型
  • MongoDB:Atlas Vector Search GA,支持 ANN 搜索
  • Redis:Redis VSS(Vector Similarity Search)模块

启示:未来可能不需要独立的向量数据库,而是选择支持向量的多模数据库。

2. 稀疏向量与混合检索成为标配

随着 LLM 的 Embeddings API 支持稀疏向量(如 SPLADE、BM25+Embedding),混合检索成为提高召回率的关键技术:

# Qdrant 的稀疏向量支持(2026 新特性)
from qdrant_client.models import SparseVector

# 稠密向量(语义相似度)
dense_vec = model.encode(query).tolist()

# 稀疏向量(关键词匹配,使用 SPLADE 生成)
sparse_vec = {
    "indices": [10, 25, 103, 5000],  # 非零元素的索引
    "values": [0.8, 0.5, 0.3, 0.9]  # 对应的权重
}

results = client.search(
    collection_name="hybrid",
    query_vector=dense_vec,
    sparse_vector={"text_sparse": sparse_vec},
    limit=10
)

3. 量化压缩技术的突破

随着向量维度的增加(如 OpenAI text-embedding-3-large 的 3072 维),量化压缩成为降低成本的必然选择:

  • INT8 量化:精度损失 < 1%,内存降低 75%
  • Binary 量化:精度损失 ~5%,内存降低 96%(适合大规模候选集召回)
  • 产品量化(PQ):将向量拆分为多个子空间分别量化,压缩比可达 16x
# Qdrant 的 Binary Quantization(2026 实验性特性)
client.create_collection(
    collection_name="binary_compressed",
    vectors_config=VectorParams(size=768, distance=Distance.COSINE),
    quantization_config=BinaryQuantizationConfig(
        always_ram=True  # 二进制向量常驻内存
    )
)
# 内存占用:768 维 * 1 bit = 96 字节/向量(对比 float32 的 3072 字节)

4. 向量数据库的 Serverless 化

随着云原生架构的普及,向量数据库正在向 Serverless 方向演进:

  • Qdrant Cloud:按实际存储和查询次数计费,自动扩缩容
  • Pinecone:无服务器索引,按需付费
  • Milvus Cloud:存算分离架构,支持弹性伸缩

总结与最佳实践

核心要点回顾

  1. 向量数据库的本质:通过 ANN 算法(HNSW、IVF-PQ)实现高维向量的快速相似度检索
  2. 四大方案对比
    • Qdrant:性能最优,Rust 实现,适合低延迟场景
    • Milvus:分布式能力最强,适合海量数据
    • Pgvector:与 Postgres 生态无缝集成,支持 ACID
    • Chroma:开发者体验最佳,适合快速原型

生产部署 Checklist

  • 容量规划:估算向量数量、维度、QPS,选择合适的主机配置
  • 索引选择:根据数据量选择 HNSW(< 1000 万)或 IVF-PQ(> 1000 万)
  • 参数调优:设置合理的 ef_construct(索引质量)和 ef(查询精度)
  • 监控告警:监控查询延迟 P99、内存使用率、索引构建进度
  • 备份策略:定期备份向量数据(Qdrant 的 Snapshots、Milvus 的 Backup、Pgvector 的 pg_dump)
  • 安全防护:启用 TLS 加密、身份认证(JWT / API Key)、网络隔离(VPC)

代码示例仓库

完整可运行的代码示例已上传到 GitHub:

  • Qdrant RAG 示例:https://github.com/example/qdrant-rag-demo
  • Milvus 分布式部署:https://github.com/example/milvus-cluster
  • Pgvector Django 集成:https://github.com/example/pgvector-django

参考资源

  1. Qdrant 官方文档:https://qdrant.tech/documentation/
  2. Milvus 性能白皮书:https://milvus.io/docs/benchmark.md
  3. Pgvector GitHub:https://github.com/pgvector/pgvector
  4. HNSW 论文:https://arxiv.org/abs/1603.09320
  5. ANN-Benchmarks:https://github.com/erikbern/ann-benchmarks

作者注:本文基于 2026 年 5 月的最新版本撰写,具体参数和性能数据可能因版本更新而变化,建议在生产部署前查阅官方文档。

复制全文 生成海报 向量数据库 Qdrant Milvus Pgvector Chroma

推荐文章

使用 `nohup` 命令的概述及案例
2024-11-18 08:18:36 +0800 CST
PHP 代码功能与使用说明
2024-11-18 23:08:44 +0800 CST
Vue3中的虚拟滚动有哪些改进?
2024-11-18 23:58:18 +0800 CST
如何在Vue 3中使用Ref访问DOM元素
2024-11-17 04:22:38 +0800 CST
CSS Grid 和 Flexbox 的主要区别
2024-11-18 23:09:50 +0800 CST
Vue中的样式绑定是如何实现的?
2024-11-18 10:52:14 +0800 CST
Rust 并发执行异步操作
2024-11-19 08:16:42 +0800 CST
页面不存在404
2024-11-19 02:13:01 +0800 CST
一个数字时钟的HTML
2024-11-19 07:46:53 +0800 CST
程序员茄子在线接单