跳到主要内容

向量数据库

向量数据库(Vector Database)是专门用于存储和检索向量数据的数据库系统。它能够高效地进行相似度搜索,是 RAG 系统的核心基础设施。本章将对比主流向量数据库的特点,帮助你做出正确的技术选型。

为什么需要向量数据库?

传统数据库无法高效处理向量相似度搜索。

传统数据库的局限

-- 传统关系型数据库:无法直接查询"相似"的文本
SELECT * FROM documents WHERE content LIKE '%机器学习%';

-- 问题:
-- 1. 只能做精确匹配,无法理解语义相似
-- 2. "AI技术"、"人工智能" 等同义词无法匹配
-- 3. 大量数据的模糊查询性能极差

向量数据库的能力

# 向量数据库:语义相似度搜索
query_embedding = embed("机器学习技术")

results = vector_db.search(
vector=query_embedding,
top_k=10
)

# 可以找到:
# "深度学习是机器学习的分支" (相似度 0.92)
# "AI技术应用场景分析" (相似度 0.87)
# "神经网络算法原理" (相似度 0.82)

向量数据库核心概念

索引类型

向量数据库使用**近似最近邻(ANN)**算法加速搜索:

索引类型原理特点适用场景
HNSW分层可导航小世界图查询极快、构建慢、内存高实时查询、中小规模
IVF倒排文件索引构建快、查询中等、内存低大规模、批量索引
PQ乘积量化内存极低、精度略损内存受限场景
Flat暴力搜索精度最高、速度最慢小数据集、精确搜索

相似度度量

度量方式公式取值范围适用场景
余弦相似度ABAB\frac{A \cdot B}{\|A\|\|B\|}[-1, 1]文本嵌入(推荐)
欧氏距离(aibi)2\sqrt{\sum(a_i - b_i)^2}[0, ∞)图像特征
点积ABA \cdot B(-∞, ∞)归一化向量等价余弦
# 不同数据库的默认度量
# Pinecone: 余弦相似度
# Milvus: 余弦相似度(可配置)
# Qdrant: 余弦相似度(可配置)
# Weaviate: 余弦相似度(可配置)

主流向量数据库对比

功能对比

特性PineconeMilvusWeaviateQdrantChroma
部署方式仅云服务自托管/云自托管/云自托管/云嵌入式
开源
混合检索
分布式
多租户
实时更新
元数据过滤

性能对比

数据库写入吞吐查询延迟扩展性内存效率
Pinecone极低自动
Milvus极高手动
Weaviate手动
Qdrant手动
Chroma

选型建议

场景推荐选择原因
快速原型Chroma零配置、嵌入式
生产云服务Pinecone免运维、高可用
大规模自托管Milvus高性能、功能全
混合检索需求Weaviate/Qdrant原生支持
资源受限Qdrant内存效率高

Pinecone

Pinecone 是全托管的向量数据库,适合追求稳定性和免运维的团队。

特点

  • 全托管,无需运维
  • 自动扩展
  • 高可用性
  • 简单易用的 API

使用示例

from pinecone import Pinecone

# 初始化
pc = Pinecone(api_key="your-api-key")

# 创建索引
pc.create_index(
name="my-index",
dimension=1536,
metric="cosine",
spec={"serverless": {"cloud": "aws", "region": "us-east-1"}}
)

# 获取索引
index = pc.Index("my-index")

# 插入向量
index.upsert([
("id1", [0.1, 0.2, ...], {"category": "tech"}),
("id2", [0.3, 0.4, ...], {"category": "news"}),
])

# 查询
results = index.query(
vector=[0.1, 0.2, ...],
top_k=10,
filter={"category": {"$eq": "tech"}}
)

定价(2024)

Serverless:
- 存储: $0.096/GB/月
- 查询: $0.096/100K 次

Pod-based:
- 从 $70/月起

Milvus

Milvus 是开源的高性能分布式向量数据库,适合大规模生产场景。

特点

  • 完全开源
  • 支持多种索引类型
  • 分布式架构
  • 丰富的检索功能

部署方式

# docker-compose.yml
version: '3.5'

services:
etcd:
image: quay.io/coreos/etcd:v3.5.5
environment:
- ETCD_AUTO_COMPACTION_MODE=revision
- ETCD_AUTO_COMPACTION_RETENTION=1000
volumes:
- etcd-data:/etcd
command: etcd -advertise-client-urls=http://127.0.0.1:2379

minio:
image: minio/minio:RELEASE.2023-03-20T20-16-18Z
environment:
MINIO_ACCESS_KEY: minioadmin
MINIO_SECRET_KEY: minioadmin
volumes:
- minio-data:/minio_data
command: minio server /minio_data

milvus:
image: milvusdb/milvus:v2.3.0
ports:
- "19530:19530"
environment:
ETCD_ENDPOINTS: etcd:2379
MINIO_ADDRESS: minio:9000
depends_on:
- etcd
- minio

volumes:
etcd-data:
minio-data:

使用示例

from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType

# 连接
connections.connect("default", host="localhost", port="19530")

# 定义 Schema
fields = [
FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True),
FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=1536),
FieldSchema(name="text", dtype=DataType.VARCHAR, max_length=2000),
FieldSchema(name="category", dtype=DataType.VARCHAR, max_length=100)
]

schema = CollectionSchema(fields=fields, description="文档集合")

# 创建集合
collection = Collection(name="documents", schema=schema)

# 创建索引
index_params = {
"metric_type": "COSINE",
"index_type": "HNSW",
"params": {"M": 16, "efConstruction": 256}
}
collection.create_index(field_name="embedding", index_params=index_params)

# 插入数据
data = [
[[0.1, 0.2, ...], "文档内容1", "tech"],
[[0.3, 0.4, ...], "文档内容2", "news"],
]
collection.insert(data)

# 加载集合
collection.load()

# 搜索
search_params = {"metric_type": "COSINE", "params": {"ef": 64}}
results = collection.search(
data=[[0.1, 0.2, ...]],
anns_field="embedding",
param=search_params,
limit=10,
expr='category == "tech"', # 过滤条件
output_fields=["text", "category"]
)

Weaviate

Weaviate 是开源的向量数据库,特色是内置向量化和混合检索。

特点

  • 内置向量化模块
  • 原生支持混合检索
  • GraphQL API
  • 丰富的模块生态

使用示例

import weaviate

# 连接
client = weaviate.Client("http://localhost:8080")

# 定义 Schema
schema = {
"class": "Document",
"properties": [
{"name": "text", "dataType": ["text"]},
{"name": "category", "dataType": ["string"]}
],
"vectorizer": "text2vec-openai" # 内置向量化
}

client.schema.create_class(schema)

# 插入数据
client.data_object.create(
class_name="Document",
data_object={"text": "文档内容", "category": "tech"}
)

# 纯向量搜索
results = (
client.query
.get("Document", ["text", "category"])
.with_near_text({"concepts": ["机器学习"]})
.with_limit(10)
.do()
)

# 混合搜索(向量 + 关键词)
results = (
client.query
.get("Document", ["text", "category"])
.with_hybrid(
query="机器学习",
alpha=0.5 # 0=纯关键词, 1=纯向量
)
.with_limit(10)
.do()
)

Qdrant

Qdrant 是高性能开源向量数据库,以内存效率著称。

特点

  • 内存效率高
  • 丰富的过滤功能
  • 量化支持
  • Rust 实现,性能优异

使用示例

from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct

# 连接
client = QdrantClient(host="localhost", port=6333)

# 创建集合
client.create_collection(
collection_name="documents",
vectors_config=VectorParams(size=1536, distance=Distance.COSINE)
)

# 插入数据
points = [
PointStruct(
id=1,
vector=[0.1, 0.2, ...],
payload={"text": "文档内容", "category": "tech"}
)
]
client.upsert(collection_name="documents", points=points)

# 搜索
results = client.search(
collection_name="documents",
query_vector=[0.1, 0.2, ...],
limit=10,
query_filter={
"must": [
{"key": "category", "match": {"value": "tech"}}
]
}
)

Chroma

Chroma 是轻量级嵌入式向量数据库,适合快速原型和小规模应用。

特点

  • 零配置、嵌入式
  • Python 友好
  • 适合原型开发
  • 支持持久化

使用示例

import chromadb
from chromadb.utils import embedding_functions

# 初始化(内存模式)
client = chromadb.Client()

# 持久化模式
# client = chromadb.PersistentClient(path="./chroma_db")

# 使用 OpenAI 嵌入
embedding_function = embedding_functions.OpenAIEmbeddingFunction(
api_key="your-api-key",
model_name="text-embedding-3-small"
)

# 创建集合
collection = client.create_collection(
name="documents",
embedding_function=embedding_function
)

# 插入数据
collection.add(
documents=["文档内容1", "文档内容2"],
metadatas=[{"category": "tech"}, {"category": "news"}],
ids=["id1", "id2"]
)

# 查询
results = collection.query(
query_texts=["机器学习"],
n_results=10,
where={"category": "tech"} # 元数据过滤
)

元数据过滤

元数据过滤可以在向量搜索前缩小范围,提高检索精度和效率。

# Pinecone
results = index.query(
vector=query_vector,
filter={
"category": {"$eq": "tech"},
"year": {"$gte": 2023}
}
)

# Milvus
results = collection.search(
data=[query_vector],
anns_field="embedding",
expr='category == "tech" and year >= 2023'
)

# Qdrant
results = client.search(
collection_name="documents",
query_vector=query_vector,
query_filter={
"must": [
{"key": "category", "match": {"value": "tech"}},
{"key": "year", "range": {"gte": 2023}}
]
}
)

混合检索

结合向量搜索和关键词搜索,提高召回率。

# Weaviate 混合检索
results = (
client.query
.get("Document", ["text"])
.with_hybrid(
query="机器学习算法",
alpha=0.5 # 平衡向量搜索和关键词搜索
)
.with_limit(10)
.do()
)

# LangChain 混合检索
from langchain.retrievers import EnsembleRetriever
from langchain_community.retrievers import BM25Retriever

# 向量检索器
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 5})

# BM25 检索器
bm25_retriever = BM25Retriever.from_documents(documents)
bm25_retriever.k = 5

# 组合
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, vector_retriever],
weights=[0.4, 0.6]
)

性能优化

索引选择

# 小数据集(< 10万):使用 Flat 索引
# 精确搜索,无精度损失

# 中等数据集(10万 - 1000万):使用 HNSW
# 平衡速度和精度

# 大数据集(> 1000万):使用 IVF + PQ
# 节省内存,支持分布式

批量操作

# 批量插入提高效率
batch_size = 1000
for i in range(0, len(documents), batch_size):
batch = documents[i:i+batch_size]
collection.insert(batch)

预热

# 搜索前加载到内存
collection.load()

小结

向量数据库是 RAG 系统的核心存储引擎,选型需考虑:

  1. 规模:小规模用 Chroma,大规模用 Milvus
  2. 运维:免运维选 Pinecone,可控性选开源方案
  3. 功能:混合检索需求选 Weaviate 或 Qdrant
  4. 成本:开源方案更省云服务费用

下一步

参考资料