向量数据库
向量数据库(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 | 暴力搜索 | 精度最高、速度最慢 | 小数据集、精确搜索 |
相似度度量
| 度量方式 | 公式 | 取值范围 | 适用场景 |
|---|---|---|---|
| 余弦相似度 | [-1, 1] | 文本嵌入(推荐) | |
| 欧氏距离 | [0, ∞) | 图像特征 | |
| 点积 | (-∞, ∞) | 归一化向量等价余弦 |
# 不同数据库的默认度量
# Pinecone: 余弦相似度
# Milvus: 余弦相似度(可配置)
# Qdrant: 余弦相似度(可配置)
# Weaviate: 余弦相似度(可配置)
主流向量数据库对比
功能对比
| 特性 | Pinecone | Milvus | Weaviate | Qdrant | Chroma |
|---|---|---|---|---|---|
| 部署方式 | 仅云服务 | 自托管/云 | 自托管/云 | 自托管/云 | 嵌入式 |
| 开源 | ❌ | ✅ | ✅ | ✅ | ✅ |
| 混合检索 | ❌ | ✅ | ✅ | ✅ | ❌ |
| 分布式 | ✅ | ✅ | ✅ | ✅ | ❌ |
| 多租户 | ✅ | ✅ | ✅ | ✅ | ❌ |
| 实时更新 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 元数据过滤 | ✅ | ✅ | ✅ | ✅ | ✅ |
性能对比
| 数据库 | 写入吞吐 | 查询延迟 | 扩展性 | 内存效率 |
|---|---|---|---|---|
| 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 系统的核心存储引擎,选型需考虑:
- 规模:小规模用 Chroma,大规模用 Milvus
- 运维:免运维选 Pinecone,可控性选开源方案
- 功能:混合检索需求选 Weaviate 或 Qdrant
- 成本:开源方案更省云服务费用