向量数据库对比

摘要

向量数据库是现代AI应用的核心基础设施,负责存储和检索高维向量数据。本文档对Pinecone、Milvus、Chroma、Weaviate、Qdrant和pgvector六大主流向量数据库进行深度对比,从架构设计、索引算法、性能表现、扩展性、成本等多维度分析,为技术选型提供系统性的决策依据。

关键词速查表

关键词说明
ANNApproximate Nearest Neighbor,近似最近邻搜索
HNSWHierarchical Navigable Small World,分层可导航小世界图
IVFInverted File Index,倒排文件索引
PQProduct Quantization,乘积量化
距离度量余弦、欧氏、内积等向量距离计算方式
混合搜索结合向量检索和关键词检索
元数据过滤支持在向量检索基础上进行属性过滤
分片数据在多个节点间的分布策略
副本数据的多份拷贝用于容错和高可用
近似精度召回率与性能的权衡指标

一、向量数据库核心概念

1.1 向量数据库的定位

向量数据库专为高维向量数据的存储和检索设计,是RAG、知识图谱、语义搜索、推荐系统等AI应用的关键基础设施。与传统关系型数据库不同,向量数据库的核心能力不是精确匹配,而是近似最近邻(ANN)搜索——在可接受的召回率损失下,快速找到与查询向量最相似的Top-K个向量。

这种能力源于深度学习模型将非结构化数据(文本、图像、音频)转化为高维向量表示。一个典型的768维向量代表一段文本的语义内容,向量间的距离反映了语义相似度。向量数据库通过优化的索引结构和距离算法,实现了毫秒级的语义检索能力。

1.2 核心索引算法

向量索引算法决定了检索的速度和精度权衡。主流算法各有特点:

HNSW(Hierarchical Navigable Small World) 是当前最流行的向量索引算法,采用分层图结构。顶层是稀疏的快速导航层,底层是密集的精确搜索层。搜索时从顶层入口点开始,逐层向下逼近,最终在底层找到最近邻。HNSW的优势在于查询速度快、精度高,但内存占用较大。

IVF(Inverted File Index) 将向量空间划分为多个聚类,搜索时只在相关聚类中进行。这种方法适合处理超大规模数据,但精度略逊于HNSW。

PQ(Product Quantization) 将高维向量压缩为低维码本表示,大幅降低存储成本,适合对内存敏感的场景。

"""
索引算法对比示意
 
实际使用时,各向量数据库已内置这些算法的实现
"""
 
index_algorithms = {
    "HNSW": {
        "query_speed": "极快",
        "build_speed": "中等",
        "memory_usage": "高",
        "recall": "高 (95%+)",
        "best_for": "追求低延迟场景"
    },
    "IVF": {
        "query_speed": "快",
        "build_speed": "快",
        "memory_usage": "中等",
        "recall": "中等 (85-95%)",
        "best_for": "超大规模数据"
    },
    "PQ": {
        "query_speed": "中等",
        "build_speed": "中等",
        "memory_usage": "低",
        "recall": "中等偏低",
        "best_for": "内存受限场景"
    },
    "HNSW + PQ": {
        "query_speed": "快",
        "build_speed": "慢",
        "memory_usage": "可调",
        "recall": "高",
        "best_for": "大规模高精度"
    }
}

1.3 距离度量

向量数据库支持多种距离度量,选择取决于向量生成模型和业务需求:

距离类型计算公式适用场景
余弦相似度cos(θ) = A·B/(|A||B|)文本Embedding、文本相似度
L2欧氏距离√(Σ(Ai-Bi)²)图像向量、通用场景
点积/内积A·B归一化向量、需要注意力权重
曼哈顿距离Σ|Ai-Bi|特定领域

二、Pinecone详解

2.1 产品定位

Pinecone是云原生的向量数据库服务,以”零运维、全托管”为核心理念。作为serverless架构的代表性产品,Pinecone让用户专注于应用开发,无需关心基础设施的运维工作。其定价基于实际使用量,按索引存储和向量查询计费。

2.2 核心架构

Pinecone采用分布式云原生架构,数据自动分片和复制,确保高可用和低延迟。服务端自动处理索引构建、查询优化和资源扩缩容。

"""
Pinecone Python SDK使用示例
 
安装: pip install pinecone-client
"""
 
from pinecone import Pinecone, ServerlessSpec
import time
 
# 初始化
pc = Pinecone(api_key="YOUR_API_KEY")
 
# 创建索引
index_name = "production-knowledge-base"
 
# 检查是否已存在
if index_name not in [idx.name for idx in pc.list_indexes()]:
    pc.create_index(
        name=index_name,
        dimension=1536,  # OpenAI ada-002 dimension
        metric="cosine",  # 余弦相似度
        spec=ServerlessSpec(
            cloud="aws",
            region="us-east-1"
        )
    )
    
    # 等待索引就绪
    while not pc.describe_index(index_name).status.ready:
        time.sleep(1)
 
# 连接索引
index = pc.Index(index_name)
 
# 插入向量
vectors = [
    {"id": "doc-001", "values": [0.1] * 1536, "metadata": {"text": "文档内容", "category": "技术"}},
    {"id": "doc-002", "values": [0.2] * 1536, "metadata": {"text": "另一文档", "category": "产品"}},
]
 
index.upsert(vectors)
 
# 查询
query_vector = [0.15] * 1536
results = index.query(
    vector=query_vector,
    top_k=10,
    include_metadata=True,
    filter={"category": {"$eq": "技术"}}  # 元数据过滤
)
 
for match in results.matches:
    print(f"ID: {match.id}, Score: {match.score}, Text: {match.metadata['text']}")
 
# 批量操作
batch_results = index.query(
    vector=[query_vector] * 5,
    top_k=5
)

2.3 核心特性

Serverless架构:用户无需预配置资源,按实际使用量付费。在流量波动场景下,这显著降低了成本。

Metadata Filtering:支持在向量检索基础上进行结构化过滤。结合向量相似度和属性条件,精确定位目标数据。

Pod类型选择:标准Pod适合通用场景;s1Pod优化存储密集型应用;p2Pod优化性能密集型工作负载。

"""
高级特性示例
"""
 
# 命名空间隔离(多租户场景)
index = pc.Index("multi-tenant-index", namespace="tenant-a")
index.upsert([...])
 
# 稀疏向量支持(混合搜索)
index.upsert([{
    "id": "doc-001",
    "values": dense_vector,  # 密集向量
    "sparse_values": {"indices": [0, 10, 20], "values": [0.1, 0.2, 0.3]}  # 稀疏
}])
 
# 索引描述和统计
stats = index.describe_index_stats()
print(f"Total vectors: {stats.total_vector_count}")
print(f"Dimension: {stats.dimension}")

2.4 优缺点分析

优势:托管服务省去运维负担、自动扩缩容稳定可靠、全球化部署低延迟、生态集成完善(OpenAI、LangChain等)。

劣势:成本随数据量线性增长、专有API锁定、自托管选项有限。

三、Milvus详解

3.1 产品定位

Milvus是Apache基金会旗下的开源向量数据库,以”高性能、大规模、强扩展”为核心定位。它支持多种部署模式,从单机到分布式集群,适合各种规模的应用场景。作为最成熟的开源向量数据库,Milvus在工业界拥有广泛的应用。

3.2 核心架构

Milvus采用分层架构设计:接入层处理客户端请求,协调节点管理集群状态,工作节点执行实际的向量操作,存储层管理数据持久化。这种架构支持水平扩展,适应业务增长。

"""
Milvus Python SDK (pymilvus) 使用示例
 
安装: pip install pymilvus
"""
 
from pymilvus import connections, Collection, FieldSchema, CollectionSchema, CollectionName, DataType, utility
import numpy as np
 
# 连接服务器
connections.connect(
    alias="default",
    host="localhost",
    port="19530"
)
 
# 定义Collection Schema
fields = [
    FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True),
    FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=768),
    FieldSchema(name="text", dtype=DataType.VARCHAR, max_length=65535),
    FieldSchema(name="category", dtype=DataType.VARCHAR, max_length=100)
]
 
schema = CollectionSchema(
    fields=fields,
    description="知识库向量集合"
)
 
# 创建Collection
collection_name = "knowledge_base"
collection = Collection(name=collection_name, schema=schema)
 
# 创建索引(提高检索效率的关键步骤)
index_params = {
    "index_type": "HNSW",
    "metric_type": "COSINE",
    "params": {"M": 16, "efConstruction": 200}
}
 
collection.create_index(
    field_name="embedding",
    index_params=index_params
)
 
# 加载到内存(查询前必须)
collection.load()
 
# 插入数据
data = [
    [i for i in range(1000)],  # 主键(自增)
    np.random.rand(1000, 768).tolist(),  # 向量
    [f"文档{i}内容" for i in range(1000)],  # 文本
    [f"category-{i%5}" for i in range(1000)]  # 类别
]
 
insert_result = collection.insert(data)
print(f"Inserted {insert_result.insert_count} entities")
 
# 查询
search_params = {"metric_type": "COSINE", "params": {"ef": 128}}
 
query_vector = np.random.rand(768).tolist()
results = collection.search(
    data=[query_vector],
    anns_field="embedding",
    param=search_params,
    limit=10,
    expr='category == "category-0"',  # 表达式过滤
    output_fields=["text", "category"]
)
 
for hits in results:
    for hit in hits:
        print(f"ID: {hit.id}, Distance: {hit.distance}, Text: {hit.entity.get('text')}")
 
# 删除索引(修改Schema前需要)
collection.release()
collection.drop_index()

3.3 分布式部署

# docker-compose.yml for Milvus Cluster
version: '3.8'
 
services:
  etcd:
    image: quay.io/coreos/etcd:v3.5.5
    environment:
      - ETCD_AUTO_COMPACTION_MODE=revision
      - ETCD_AUTO_COMPACTION_RETENTION=1000
      - ETCD_QUOTA_BACKEND_BYTES=4294967296
    volumes:
      - etcd_data:/etcd
    command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
 
  minio:
    image: minio/minio:RELEASE.2023-03-20T20-16-18Z
    environment:
      MINIO_ACCESS_KEY: minioadmin
      MINIO_SECRET_KEY: minioadmin
    volumes:
      - minio_data:/minio
    command: minio server /minio --console-address ":9001"
 
  milvus:
    image: milvusdb/milvus:v2.3.3
    command: ["milvus", "run", "standalone"]
    environment:
      ETCD_ENDPOINTS: etcd:2379
      MINIO_ADDRESS: minio:9000
    volumes:
      - milvus_data:/var/lib/milvus
    ports:
      - "19530:19530"
      - "9091:9091"
 
volumes:
  etcd_data:
  minio_data:
  milvus_data:

3.4 优缺点分析

优势:完全开源可自托管、水平扩展能力强、社区活跃度高、支持多种索引类型、性价比高。

劣势:运维复杂度较高(相对Pinecone)、单机性能略逊于专用优化版本、学习曲线较陡。

四、Chroma详解

4.1 产品定位

Chroma是专为AI应用设计的开源向量数据库,以”开发者友好、嵌入应用内置”为核心理念。它可以嵌入Python应用进程运行,无需独立部署,适合原型开发和小型应用。Chroma的设计哲学是 simplicity first,为LangChain等AI框架提供无缝集成。

4.2 核心架构

Chroma的核心是轻量级的本地向量存储,支持文件持久化和客户端-服务器两种模式。这种设计使其成为AI应用开发的理想选择。

"""
Chroma Python SDK使用示例
 
安装: pip install chromadb
"""
 
import chromadb
from chromadb.config import Settings
import numpy as np
 
# 方式1: 内存模式(临时数据)
client = chromadb.Client()
 
# 方式2: 持久化模式
client = chromadb.PersistentClient(path="./chroma_data")
 
# 方式3: 客户端-服务器模式
client = chromadb.HttpClient(host="localhost", port=8000)
 
# 创建Collection
collection = client.create_collection(
    name="knowledge_base",
    metadata={"description": "知识库向量集合"},  # 集合级别的元数据
    get_or_create=True
)
 
# 添加向量
collection.add(
    ids=["doc-001", "doc-002", "doc-003"],
    embeddings=np.random.rand(3, 384).tolist(),  # BGE-small dimension
    documents=[
        "机器学习是人工智能的核心技术",
        "深度学习是机器学习的子领域",
        "自然语言处理处理文本数据"
    ],
    metadatas=[
        {"source": "技术文档", "category": "AI"},
        {"source": "技术文档", "category": "深度学习"},
        {"source": "技术文档", "category": "NLP"}
    ]
)
 
# 查询
query_embedding = np.random.rand(384).tolist()
results = collection.query(
    query_embeddings=[query_embedding],
    n_results=2,
    where={"category": "AI"},  # 元数据过滤
    include=["documents", "metadatas", "distances"]
)
 
print(f"IDs: {results['ids']}")
print(f"Distances: {results['distances']}")
print(f"Documents: {results['documents']}")
 
# 更新和删除
collection.update(
    ids=["doc-001"],
    embeddings=[np.random.rand(384).tolist()],
    documents=["更新后的文档内容"]
)
 
collection.delete(ids=["doc-003"], where={"category": "NLP"})
 
# Collection管理
collection_list = client.list_collections()
print(f"Collections: {[c.name for c in collection_list]}")
 
collection_info = collection.get()
print(f"Count: {collection_info.count()}")

4.3 与LangChain集成

"""
Chroma与LangChain集成示例
 
安装: pip install langchain-chroma
"""
 
from langchain_chroma import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import TextLoader
 
# 初始化Embedding模型
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
 
# 创建Chroma向量存储
vectorstore = Chroma(
    client=chromadb.PersistentClient(path="./chroma_data"),
    collection_name="langchain_docs",
    embedding_function=embeddings
)
 
# 加载文档
loader = TextLoader("./knowledge_base.txt")
documents = loader.load()
 
# 文本分割
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,
    chunk_overlap=200
)
chunks = text_splitter.split_documents(documents)
 
# 向量化存储
vectorstore.add_documents(chunks)
 
# 相似性检索
results = vectorstore.similarity_search(
    "什么是机器学习",
    k=5,
    filter={"source": "技术文档"}
)
 
for doc in results:
    print(f"Content: {doc.page_content[:100]}...")
    print(f"Metadata: {doc.metadata}")

4.4 优缺点分析

优势:零配置使用、学习曲线极低、与AI框架无缝集成、轻量级适合原型开发、完全开源。

劣势:单机模式不适合大规模生产环境、客户端-服务器模式功能受限、不支持分布式部署、持久化性能一般。

五、Weaviate详解

5.1 产品定位

Weaviate是以”知识图谱+向量搜索”融合为特色的向量数据库。它原生支持混合搜索,结合向量相似度和结构化属性过滤,适合构建知识图谱增强的智能应用。Weaviate提供云服务和企业版,同时保持完全开源。

5.2 核心架构

Weaviate采用模块化架构设计,核心引擎支持多种向量化模块(如OpenAI、 Cohere、本地模型)。它原生存储JSON格式的对象,与GraphQL风格的查询接口。

"""
Weaviate Python SDK使用示例
 
安装: pip install weaviate-client
"""
 
import weaviate
from weaviate.classes.init import Auth
import numpy as np
 
# 初始化客户端
client = weaviate.Client(
    url="http://localhost:8080",
    # auth_client_secret=Auth.api_key("YOUR-WEAVIATE-API-KEY")  # 云服务认证
)
 
# 创建Collection(Schema定义)
if not client.collections.exists("Article"):
    article_collection = client.collections.create(
        name="Article",
        properties=[
            weaviate.classes.config.Property(name="title", data_type=weaviate.classes.config.DataType.TEXT),
            weaviate.classes.config.Property(name="content", data_type=weaviate.classes.config.DataType.TEXT),
            weaviate.classes.config.Property(name="author", data_type=weaviate.classes.config.DataType.TEXT),
            weaviate.classes.config.Property(name="publish_year", data_type=weaviate.classes.config.DataType.INT),
            weaviate.classes.config.Property(name="tags", data_type=weaviate.classes.config.DataType.TEXT_ARRAY)
        ],
        vectorizer_config=[
            weaviate.classes.config.Configure.NamedVectorizer.text2vec_transformers(
                vectorize_collection_name=False
            )
        ],
        vector_index_config=weaviate.classes.config.Configure.VectorIndex.HNSW(
            distance_metric=weaviate.classes.config.VectorDistances.COSINE
        )
    )
 
# 插入数据
article_collection = client.collections.get("Article")
 
data_objects = [
    {
        "title": "深度学习导论",
        "content": "深度学习是机器学习的一个分支...",
        "author": "张三",
        "publish_year": 2023,
        "tags": ["AI", "深度学习", "机器学习"]
    },
    {
        "title": "自然语言处理基础",
        "content": "NLP处理文本和语音数据...",
        "author": "李四",
        "publish_year": 2024,
        "tags": ["NLP", "AI", "语言"]
    }
]
 
# 使用内置向量化器自动生成向量
article_collection.data.insert_many(data_objects)
 
# 手动指定向量
article_collection.data.insert(
    properties={
        "title": "计算机视觉进展",
        "content": "CV领域的重要突破...",
        "author": "王五"
    },
    vector=np.random.rand(768).tolist()
)
 
# 混合搜索(向量+关键词)
articles = article_collection.query.hybrid(
    query="机器学习",
    vector=np.random.rand(768).tolist(),  # 可选:结合向量搜索
    alpha=0.7,  # 0=纯关键词, 1=纯向量
    limit=10,
    filters=weaviate.classes.query.Filter.by_property("publish_year").greater_than(2022),
    return_properties=["title", "content", "author"],
    return_metadata=weaviate.classes.query.MetadataQuery.full()
)
 
for obj in articles.objects:
    print(f"Title: {obj.properties['title']}")
    print(f"Score: {obj.metadata.score}")
 
# 纯向量搜索
articles = article_collection.query.near_vector(
    near_vector=np.random.rand(768).tolist(),
    limit=10,
    filters=weaviate.classes.query.Filter.by_property("tags").contains_any(["AI"])
)

5.3 GraphQL查询

"""
Weaviate GraphQL查询示例
"""
 
# GraphQL方式查询
query = """
{
  Get {
    Article(
      nearText: {
        concepts: ["人工智能"]
        moveTo: {
          concepts: ["机器学习"],
          force: 0.5
        }
        moveAwayFrom: {
          concepts: ["硬件"],
          force: 0.3
        }
      }
      limit: 10
    ) {
      title
      content
      _additional {
        certainty
        distance
      }
    }
  }
}
"""
 
result = client.query.raw(query)
print(result)

5.4 优缺点分析

优势:知识图谱原生支持、混合搜索能力强、多向量化模块集成、GraphQL接口灵活、GraphQL订阅支持实时更新。

劣势:学习曲线较陡(GraphQL API)、资源占用较高、分布式功能需要企业版。

六、Qdrant详解

6.1 产品定位

Qdrant是高性能的开源向量搜索引擎,以”速度优先、灵活筛选”为设计理念。它提供精确的控制能力和优秀的性能表现,特别适合需要细粒度检索控制的场景。Qdrant支持本地部署和云服务,社区活跃度高。

6.2 核心架构

Qdrant采用Rust语言实现,在性能和内存效率上有显著优势。它支持多种距离度量、丰富的过滤表达式和稀疏-密集混合向量。

"""
Qdrant Python SDK使用示例
 
安装: pip install qdrant-client
"""
 
from qdrant_client import QdrantClient, models
from qdrant_client.models import Distance, VectorParams, PointStruct, Filter
import numpy as np
 
# 连接Qdrant服务
client = QdrantClient(host="localhost", port=6333)
 
# 创建Collection
collection_name = "knowledge_base"
 
# 删除已存在的Collection(可选)
if client.collection_exists(collection_name):
    client.delete_collection(collection_name)
 
# 创建Collection,指定向量参数
client.create_collection(
    collection_name=collection_name,
    vectors_config=VectorParams(
        size=768,  # 向量维度
        distance=Distance.COSINE  # 距离度量
    ),
    # 稀疏向量配置(可选)
    sparse_vectors_config=models.SparseVectorParams(
        index=models.SparseIndexParams(
            on_disk=False
        )
    )
)
 
# 配置HNSW索引参数
client.update_collection(
    collection_name=collection_name,
    hnsw_config=models.HnswConfigDiff(
        m=16,  # 节点连接数
        ef_construct=200,  # 构建时探索因子
        full_scan_threshold=10000  # 小于此规模用全扫描
    )
)
 
# 插入向量
points = [
    PointStruct(
        id="doc-001",
        vector=np.random.rand(768).tolist(),
        payload={
            "text": "机器学习是人工智能的核心技术",
            "category": "AI",
            "created_at": "2024-01-01",
            "score_range": 85
        }
    ),
    PointStruct(
        id="doc-002",
        vector=np.random.rand(768).tolist(),
        payload={
            "text": "深度学习使用神经网络",
            "category": "深度学习",
            "created_at": "2024-01-15",
            "score_range": 90
        }
    )
]
 
client.upsert(
    collection_name=collection_name,
    points=points
)
 
# 高级查询
search_results = client.search(
    collection_name=collection_name,
    query_vector=np.random.rand(768).tolist(),
    query_filter=Filter(
        must=[
            models.FieldCondition(
                key="category",
                match=models.MatchValue(value="AI")
            ),
            models.FieldCondition(
                key="score_range",
                range=models.Range(gte=80)
            )
        ],
        should=[
            models.FieldCondition(
                key="created_at",
                match=models.MatchText(text="2024")
            )
        ]
    ),
    limit=10,
    score_threshold=0.7,  # 最低分数阈值
    with_payload=True,
    with_vectors=False
)
 
for result in search_results:
    print(f"ID: {result.id}")
    print(f"Score: {result.score}")
    print(f"Payload: {result.payload}")
 
# 批量搜索
query_vectors = [np.random.rand(768).tolist() for _ in range(3)]
batch_results = client.search_batch(
    collection_name=collection_name,
    requests=[
        models.SearchRequest(
            vector=qv,
            limit=5,
            filter=Filter(must=[models.FieldCondition(key="category", match=models.MatchValue(value="AI"))])
        )
        for qv in query_vectors
    ]
)

6.3 重组与更新

"""
Qdrant重组(Re-ranking)和条件更新
"""
 
# 重组查询 - 在初步向量搜索后进行精确排序
result = client.search(
    collection_name=collection_name,
    query_vector=query_vector,
    limit=20,  # 初步返回更多结果
    search_params=models.SearchParams(hnsw_ef=128)
)
 
# 使用不同策略重组
reranked = sorted(
    result,
    key=lambda x: (x.score * 0.7 + x.payload.get('score_range', 0) / 100 * 0.3),
    reverse=True
)
 
# 条件更新
client.update_collection(
    collection_name=collection_name,
    optimizer_config=models.OptimizersConfigDiff(
        indexing_threshold=20000,  # 触发索引建立的向量数
        memmap_threshold_kb=1024
    )
)
 
# 删除向量
client.delete(
    collection_name=collection_name,
    points_selector=models.PointIdsList(
        points=["doc-001", "doc-002"]
    )
)
 
# 条件删除
client.delete(
    collection_name=collection_name,
    points_selector=models.FilterSelector(
        filter=Filter(
            must=[
                models.FieldCondition(
                    key="category",
                    match=models.MatchValue(value="deprecated")
                )
            ]
        )
    )
)

6.4 优缺点分析

优势:Rust实现性能卓越、过滤表达式丰富灵活、稀疏-密集混合支持、成熟度高的开源项目、详尽的文档和API。

劣势:生态系统相对年轻、托管服务相对新、没有内置知识图谱功能。

七、pgvector详解

7.1 产品定位

pgvector是PostgreSQL的向量搜索扩展,将向量存储能力融入成熟的关系型数据库。对于已有PostgreSQL基础设施的团队,pgvector提供了零新增基础设施的向量搜索方案。它支持向量存储、相似度搜索和精确的KNN(最近邻)操作。

7.2 核心功能

-- 安装扩展
CREATE EXTENSION IF NOT EXISTS vector;
 
-- 创建带向量列的表
CREATE TABLE documents (
    id SERIAL PRIMARY KEY,
    title VARCHAR(500),
    content TEXT,
    embedding vector(768),  -- 768维向量(可调)
    category VARCHAR(100),
    created_at TIMESTAMP DEFAULT NOW()
);
 
-- 创建HNSW索引(推荐用于生产环境)
CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops);
 
-- 或创建IVFFlat索引(适合超大数据集)
CREATE INDEX ON documents USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
 
-- 插入数据
INSERT INTO documents (title, content, embedding, category)
VALUES 
    ('深度学习入门', '深度学习是机器学习的分支...', 
     '[0.1, 0.2, ...]::vector', 'AI'),
    ('Python教程', 'Python是一门编程语言...', 
     '[0.3, 0.4, ...]::vector', '编程');
 
-- 基础相似度查询
SELECT title, content, 
       1 - (embedding <=> '[0.1, 0.2, ...]::vector') AS similarity
FROM documents
ORDER BY embedding <=> '[0.1, 0.2, ...]::vector'
LIMIT 5;
 
-- 精确KNN查询
SELECT * FROM documents
ORDER BY embedding <-> '[0.1, 0.2, ...]::vector'
LIMIT 10;
 
-- 距离操作符说明
-- <=> 余弦距离 (1 - cosine_similarity)
-- <+> L2欧氏距离
-- <#> 负内积

7.3 Python集成

"""
pgvector与Python生态集成
 
安装: pip install psycopg2-binary pgvector
"""
 
import psycopg2
import numpy as np
 
# 连接数据库
conn = psycopg2.connect(
    host="localhost",
    database="vector_db",
    user="postgres",
    password="password"
)
cursor = conn.cursor()
 
# 执行向量搜索
def search_similar(query_embedding, top_k=10, category=None):
    query_vec = "[" + ",".join(map(str, query_embedding)) + "]"
    
    sql = """
        SELECT id, title, content,
               1 - (embedding <=> %s::vector) AS similarity
        FROM documents
        WHERE 1=1
    """
    params = [query_vec]
    
    if category:
        sql += " AND category = %s"
        params.append(category)
    
    sql += f"""
        ORDER BY embedding <=> %s::vector
        LIMIT {top_k}
    """
    
    cursor.execute(sql, params)
    return cursor.fetchall()
 
# 批量插入
def batch_insert(documents):
    """批量插入文档和向量"""
    values = []
    params = []
    
    for doc in documents:
        vec_str = "[" + ",".join(map(str, doc["embedding"])) + "]"
        values.append("(%s, %s, %s, %s::vector)")
        params.extend([doc["title"], doc["content"], doc["category"], vec_str])
    
    sql = """
        INSERT INTO documents (title, content, category, embedding)
        VALUES """ + ",".join(values)
    
    cursor.execute(sql, params)
    conn.commit()
 
# 搜索示例
query_emb = np.random.rand(768)
results = search_similar(query_emb, top_k=5, category="AI")
 
for row in results:
    print(f"ID: {row[0]}, Title: {row[1]}, Similarity: {row[3]:.4f}")

7.4 与SQLAlchemy集成

"""
使用SQLAlchemy操作pgvector
 
安装: pip install sqlalchemy[postgresql] sqlalchemy-utils
"""
 
from sqlalchemy import create_engine, Column, Integer, String, Text, Float
from sqlalchemy.dialects.postgresql import ARRAY
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
import numpy as np
 
Base = declarative_base()
 
class Document(Base):
    __tablename__ = "documents"
    
    id = Column(Integer, primary_key=True)
    title = Column(String(500))
    content = Column(Text)
    category = Column(String(100))
    # pgvector列使用String存储,向量操作时CAST
    embedding = Column(String)  # 存储为字符串 "[0.1, 0.2, ...]"
    
    def get_embedding_array(self):
        return np.array(eval(self.embedding))
    
    def set_embedding_array(self, arr):
        self.embedding = str(arr.tolist())
 
engine = create_engine("postgresql://postgres:password@localhost/vector_db")
Base.metadata.create_all(engine)
 
Session = sessionmaker(bind=engine)
session = Session()
 
# 添加文档
doc = Document(
    title="机器学习基础",
    content="机器学习是人工智能的重要分支...",
    category="AI"
)
doc.set_embedding_array(np.random.rand(768))
session.add(doc)
session.commit()
 
# 相似性搜索
def search_documents(query_embedding, limit=10):
    vec_str = str(query_embedding.tolist())
    
    results = session.execute(
        f"""
        SELECT id, title, content, category,
               1 - (embedding::vector <=> '{vec_str}'::vector) AS similarity
        FROM documents
        ORDER BY embedding::vector <=> '{vec_str}'::vector
        LIMIT {limit}
        """
    )
    
    return [(row[0], row[1], row[4]) for row in results]

7.5 优缺点分析

优势:零新增基础设施、与现有Postgres生态完美集成、事务支持强(ACID)、支持复杂SQL联接、免费开源。

劣势:向量索引性能不如专用向量数据库、大规模向量(百万级)性能下降、水平扩展需要PostgreSQL原生分片。

八、综合对比矩阵

8.1 功能特性对比

特性PineconeMilvusChromaWeaviateQdrantpgvector
部署模式全托管自托管/云嵌入/服务器自托管/云自托管/云自托管
开源
HNSW
IVF
混合搜索
元数据过滤
稀疏向量
知识图谱
分布式自动支持企业版支持受限
多租户

8.2 性能对比

基于10M 768维向量的基准测试(来源:ANN-Benchmark等公开数据):

数据库QPSP99延迟召回率内存占用
Qdrant1500+50ms98%
Milvus1200+80ms97%
Weaviate800+100ms96%
Pinecone1000+60ms97%托管
Chroma500+150ms95%
pgvector300+200ms99%

测试说明

测试条件:10M向量,HNSW索引(M=16, efConstruction=200),V100 GPU环境。实际性能因数据分布、查询复杂度而异。

8.3 成本对比

数据库免费额度1M向量/月扩展成本
Pinecone~$70-200按使用量
Milvus~$50-100*基础设施
Chroma~$0-20*基础设施
Weaviate~$60-150*基础设施+云服务
Qdrant~$40-80*基础设施+云服务
pgvector~$30-60*基础设施

*估算,基于典型云服务器成本

8.4 选型决策树

开始
  │
  ├─ 是否已有PostgreSQL基础设施?
  │     │
  │     ├─ 是 → pgvector(零成本扩展)
  │     └─ 否
  │           │
  │           ├─ 是否需要知识图谱能力?
  │           │     │
  │           │     ├─ 是 → Weaviate
  │           │     └─ 否
  │           │           │
  │           │           ├─ 团队规模 < 5人,原型开发?
  │           │           │     │
  │           │           │     ├─ 是 → Chroma
  │           │           │     └─ 否
  │           │           │           │
  │           │           │           ├─ 是否需要托管服务?
  │           │           │           │     │
  │           │           │           │     ├─ 是 → Pinecone
  │           │           │           │     └─ 否 → Qdrant / Milvus
  │           │           │           │
  │           │           └─ 规模 > 100M向量?
  │           │                 │
  │           │                 ├─ 是 → Milvus(分布式支持)
  │           │                 └─ 否 → Qdrant(性能优先)
  │           │
  │           └─ 是否追求极致性能?
  │                 │
  │                 ├─ 是 → Qdrant
  │                 └─ 否 → 根据其他因素选择
  │
  结束

九、相关主题链接


更新日志

  • 2026-04-18: 初始版本完成
  • 涵盖6大主流向量数据库的全面对比
  • 提供详尽的代码示例和选型决策指南