向量数据库入门:从原理到选型
对比 Pinecone、Milvus、Chroma、Weaviate 等主流向量数据库的特点与适用场景
为什么需要向量数据库
上一篇我们聊了 Embedding,知道了文本可以变成向量。但问题来了——当你有 100 万条文档,每条都是 1536 维的向量,你怎么快速找到跟用户查询最相似的那几条?
暴力搜索?遍历 100 万条向量,每条做一次余弦相似度计算。可以,但太慢了。
# 暴力搜索 - O(n) 复杂度
for doc in all_documents: # 100 万次循环
similarity = cosine_similarity(query_vector, doc.vector) # 1536 维点积
这就是向量数据库要解决的核心问题:在海量向量中快速找到最相似的 Top-K。
传统数据库为什么不行
| 特性 | 传统数据库 (MySQL/PostgreSQL) | 向量数据库 |
|---|---|---|
| 数据类型 | 结构化数据(行、列) | 高维向量 |
| 查询方式 | 精确匹配 (WHERE id = 1) | 近似最近邻 (ANN) |
| 索引类型 | B-Tree、Hash | HNSW、IVF、PQ |
| 相似度搜索 | 不原生支持 | 核心功能 |
| 百万级搜索延迟 | 秒级(全表扫描) | 毫秒级 |
当然,PostgreSQL 有 pgvector 扩展可以做向量搜索,SQLite 也有类似方案。对于小规模数据(几十万条以内),这些方案完全够用。但当数据量上去之后,专用向量数据库的优势就体现出来了。
向量搜索的核心:ANN 算法
ANN (Approximate Nearest Neighbor) 是向量搜索的核心。它不追求找到绝对最近的邻居,而是用极小的精度损失换取巨大的速度提升。
HNSW (Hierarchical Navigable Small World)
目前最主流的 ANN 算法。想象一个多层的图结构:
第 3 层 (最稀疏): A -------- D
| |
第 2 层: A --- B -- D
| | |
第 1 层: A-B--C-D-E-F
| | | | | |
第 0 层 (最密集): A-B-C-D-E-F-G-H-I-J
搜索时从最高层开始,快速定位到大致区域,然后逐层下降,越来越精确。就像先看世界地图找到国家,再看省级地图找到城市,最后看街道地图找到具体位置。
特点:
- 搜索速度快,O(log n)
- 内存占用较高(需要存储图结构)
- 支持动态插入和删除
- 大多数向量数据库的默认选择
IVF (Inverted File Index)
先把向量空间划分成若干个聚类(Voronoi 区域),搜索时只在最近的几个聚类中查找:
聚类 1: [v1, v5, v8, v12, ...]
聚类 2: [v2, v3, v9, v15, ...]
聚类 3: [v4, v6, v7, v11, ...]
...
查询 q → 找到最近的聚类 2 和 3 → 只在这两个聚类中搜索
特点:
- 需要预先训练聚类中心
- 内存占用较低
- 适合静态数据集
- 可以和 PQ 结合进一步压缩
PQ (Product Quantization)
把高维向量切分成多个子空间,每个子空间独立量化压缩:
原始向量 (1536 维):
[0.21, -0.45, 0.78, ..., 0.33]
切分为 192 个子空间,每个 8 维:
[0.21, -0.45, ...] [0.78, 0.12, ...] ... [0.33, -0.11, ...]
每个子空间量化为一个 ID:
[42] [17] ... [89]
压缩比: 1536 × 4 bytes → 192 × 1 byte = 32x 压缩
特点:
- 极大减少内存占用
- 有一定精度损失
- 通常和 IVF 配合使用 (IVF-PQ)
主流向量数据库对比
一览表
| 数据库 | 类型 | 开源 | 托管服务 | 适合场景 | ANN 算法 |
|---|---|---|---|---|---|
| Pinecone | 云原生 | 否 | 是 | 生产环境,不想运维 | 自研 |
| Milvus | 分布式 | 是 | Zilliz Cloud | 大规模生产环境 | HNSW, IVF, PQ |
| Chroma | 嵌入式 | 是 | 是 | 原型开发,小规模 | HNSW |
| Weaviate | 分布式 | 是 | 是 | 需要混合搜索 | HNSW |
| Qdrant | 分布式 | 是 | 是 | 高性能,Rust 编写 | HNSW |
| pgvector | 扩展 | 是 | 随 PG | 已有 PostgreSQL 基础设施 | IVF, HNSW |
Pinecone
优点:
✓ 全托管,零运维
✓ 自动扩缩容
✓ Serverless 模式按用量计费
缺点:
✗ 不开源,供应商锁定
✗ 自定义能力有限
✗ 数据必须存在 Pinecone 的云上
Milvus
优点:
✓ 开源,社区活跃
✓ 支持多种索引类型
✓ 分布式架构,支持十亿级向量
✓ 有托管服务 Zilliz Cloud
缺点:
✗ 部署和运维相对复杂
✗ 资源消耗较大
Chroma
优点:
✓ 极简 API,几行代码就能用
✓ 嵌入式模式,无需额外服务
✓ 和 LangChain/LlamaIndex 集成好
✓ 适合快速原型开发
缺点:
✗ 不适合大规模生产
✗ 功能相对简单
Weaviate
优点:
✓ 内置向量化模块(可以自动 Embedding)
✓ 支持混合搜索(向量 + 关键词)
✓ GraphQL API
✓ 多租户支持
缺点:
✗ 学习曲线稍陡
✗ 内存占用较高
Qdrant
优点:
✓ Rust 编写,性能优秀
✓ 支持丰富的过滤条件
✓ 内存和磁盘混合存储
✓ API 设计简洁
缺点:
✗ 生态相对年轻
✗ 社区规模较小
实战:用 Chroma 构建语义搜索
Chroma 是最适合入门的向量数据库。我们来用它构建一个简单的语义搜索系统。
安装
pip install chromadb openai
基本用法
import chromadb
from openai import OpenAI
# 创建 Chroma 客户端(内存模式)
chroma_client = chromadb.Client()
# 创建一个 collection(类似数据库中的表)
collection = chroma_client.create_collection(
name="my_docs",
metadata={"hnsw:space": "cosine"} # 使用余弦相似度
)
# 准备文档
documents = [
"Python 是一门简洁优雅的编程语言,适合初学者入门",
"JavaScript 是 Web 开发的核心语言,前后端都能用",
"Rust 以内存安全和高性能著称,适合系统编程",
"机器学习是人工智能的一个分支,通过数据训练模型",
"深度学习使用神经网络处理复杂的模式识别任务",
"Docker 是一种容器化技术,简化了应用部署流程",
]
# 添加文档(Chroma 可以自动生成 Embedding)
collection.add(
documents=documents,
ids=[f"doc_{i}" for i in range(len(documents))]
)
# 搜索
results = collection.query(
query_texts=["如何学习编程"],
n_results=3
)
print("搜索结果:")
for doc, distance in zip(results["documents"][0], results["distances"][0]):
print(f" [{distance:.4f}] {doc}")
使用 OpenAI Embedding
import chromadb
from chromadb.utils import embedding_functions
# 使用 OpenAI 的 Embedding 模型
openai_ef = embedding_functions.OpenAIEmbeddingFunction(
api_key="your-api-key",
model_name="text-embedding-3-small"
)
# 创建 collection 时指定 Embedding 函数
collection = chroma_client.create_collection(
name="my_docs_openai",
embedding_function=openai_ef
)
# 后续用法完全一样
collection.add(
documents=documents,
ids=[f"doc_{i}" for i in range(len(documents))]
)
持久化存储
# 使用持久化客户端,数据存到磁盘
chroma_client = chromadb.PersistentClient(path="./chroma_data")
# 之后的用法完全一样
# 重启程序后数据还在
带元数据过滤
# 添加文档时附带元数据
collection.add(
documents=["Python 入门教程", "Python 高级技巧", "Java 入门教程"],
metadatas=[
{"language": "python", "level": "beginner"},
{"language": "python", "level": "advanced"},
{"language": "java", "level": "beginner"}
],
ids=["doc_0", "doc_1", "doc_2"]
)
# 搜索时过滤
results = collection.query(
query_texts=["编程入门"],
n_results=3,
where={"language": "python"} # 只搜索 Python 相关的
)
选型指南:该用哪个
按项目阶段选
原型开发 / 个人项目
→ Chroma(嵌入式,零配置)
中小规模生产(< 100 万向量)
→ Qdrant 或 Weaviate(单机部署)
→ pgvector(如果已有 PostgreSQL)
大规模生产(> 1000 万向量)
→ Milvus(分布式,开源)
→ Pinecone(托管,省心)
不想运维
→ Pinecone Serverless
→ Zilliz Cloud (Milvus 托管版)
→ Weaviate Cloud
按功能需求选
| 需求 | 推荐 |
|---|---|
| 快速原型 | Chroma |
| 混合搜索(向量 + 关键词) | Weaviate |
| 极致性能 | Qdrant |
| 大规模分布式 | Milvus |
| 零运维 | Pinecone |
| 已有 PostgreSQL | pgvector |
| 多租户 | Weaviate, Qdrant |
与 LLM 应用的集成
向量数据库在 LLM 应用中最常见的角色是 RAG 的检索层:
用户提问
↓
Embedding 模型 → 查询向量
↓
向量数据库 → 检索相关文档
↓
LLM + 相关文档 → 生成回答
主流框架都有很好的集成:
# LangChain + Chroma
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
vectorstore = Chroma.from_documents(
documents=docs,
embedding=OpenAIEmbeddings()
)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
results = retriever.invoke("什么是向量数据库")
# LlamaIndex + Chroma
from llama_index.core import VectorStoreIndex
from llama_index.vector_stores.chroma import ChromaVectorStore
vector_store = ChromaVectorStore(chroma_collection=collection)
index = VectorStoreIndex.from_vector_store(vector_store)
query_engine = index.as_query_engine()
response = query_engine.query("什么是向量数据库")
性能优化建议
1. 选择合适的索引类型
数据量 < 10 万: 暴力搜索 (Flat) 就够了
数据量 10 万 - 1000 万: HNSW
数据量 > 1000 万: IVF-PQ 或 HNSW + PQ
2. 调整 HNSW 参数
# Milvus 示例
index_params = {
"index_type": "HNSW",
"metric_type": "COSINE",
"params": {
"M": 16, # 每个节点的连接数,越大越精确但越慢
"efConstruction": 200 # 构建时的搜索宽度
}
}
3. 合理使用过滤
先过滤再搜索(pre-filtering)比先搜索再过滤(post-filtering)更高效,但不是所有数据库都支持。Qdrant 和 Weaviate 在这方面做得比较好。
4. 批量操作
# 好的做法:批量插入
collection.add(
documents=all_documents, # 一次性插入
ids=all_ids
)
# 不好的做法:逐条插入
for doc, id in zip(all_documents, all_ids):
collection.add(documents=[doc], ids=[id]) # 每次一条,很慢
总结
向量数据库是 AI 应用的基础设施。选择时不必纠结”最好的”,而是选”最适合当前阶段的”:
- 刚开始探索?用 Chroma,几行代码就能跑
- 准备上生产?评估 Qdrant、Weaviate 或 Milvus
- 不想操心运维?Pinecone 或各家的云服务
向量数据库让 AI 拥有了”记忆”。有了它,我们的 LLM 应用才能从”只会聊天”进化到”真正有用”。下一篇我们来聊 RAG——把向量数据库和 LLM 串起来的完整架构。
相关文章
评论
加载中...
评论
加载中...