向量数据库从入门到生产(上):概念、选型与快速上手
作者:唐璜Taro | AI 教程系列 | 适合读者:零基础开发者
阅读时间:约 25 分钟
系列:本文为上篇,下篇见 →[ [《向量数据库从入门到生产(下):生产实践与 Agent 集成》](https://blog.csdn.net/weixin_44067347/article/details/161272114))
目录
第一章:什么是向量数据库
1.1 从一个生活场景说起
假设你去图书馆找一本关于"如何做红烧肉"的书:
- 关系数据库的做法:你去查书名目录,精确匹配"红烧肉"三个字。如果书名是《家常菜烹饪技巧》,哪怕内容 90% 讲红烧肉,你也找不到。
- 向量数据库的做法:你告诉图书管理员"我想学做红烧肉",管理员理解你的语义,把《家常菜烹饪技巧》《中华料理大全》甚至《酱油的妙用》都推荐给你——因为它们在内容含义上和你的需求接近。
这就是向量数据库的核心能力:基于语义相似度的模糊搜索。

1.2 什么是向量(Embedding)
在计算机的世界里,文字、图片、音频本身不能直接计算"相似度"。我们需要先把它们转换成一组数字,这组数字就叫向量(Vector),转换的过程叫Embedding(嵌入)。
举个例子:
"红烧肉" → [0.23, -0.45, 0.87, 0.12, ..., 0.56] (1536 个数字)
"家常菜" → [0.21, -0.42, 0.85, 0.15, ..., 0.53] (很接近!)
"量子力学" → [-0.78, 0.33, -0.12, 0.91, ..., -0.44] (差很远)
向量之间的距离(余弦相似度、欧氏距离等)就代表了原始内容的语义相似程度。
1.3 向量数据库 vs 关系数据库
| 维度 | 关系数据库(MySQL/PostgreSQL) | 向量数据库(Milvus/Chroma) |
|---|---|---|
| 数据模型 | 二维表(行和列) | 高维向量 + 标量字段 |
| 查询方式 | SQL 精确匹配(WHERE name = '张三') | 相似度搜索(“找最像张三的人”) |
| 索引原理 | B+Tree / Hash | ANN(近似最近邻)算法 |
| 典型场景 | 事务处理、CRUD、报表 | 语义搜索、推荐系统、RAG |
| 数据规模 | 百万到亿级记录 | 万到百亿级向量 |
| 一致性 | 强一致性(ACID) | 最终一致性(大部分) |
| 查询结果 | 精确结果集 | Top-K 近似结果 |
| 代表产品 | MySQL、PostgreSQL、Oracle | Milvus、Pinecone、Weaviate |
关键区别总结:
- 关系数据库回答的是:“这个数据在哪里?”(精确查找)
- 向量数据库回答的是:“哪些数据和这个最像?”(相似搜索)
1.4 为什么需要向量数据库?
你可能会问:我把所有向量存到 MySQL 里,遍历计算相似度不行吗?
答案是:可以,但很慢。
假设你有 100 万个向量,每个 1536 维。每次查询要计算 100 万次余弦相似度,这在实时场景下是不可接受的。
向量数据库通过专用的 ANN 索引(如 HNSW、IVF),把搜索复杂度从 O(n) 降到 O(log n) 甚至更低,让亿级向量的毫秒级搜索成为可能。
第二章:主流向量数据库选型
2.1 全景图
┌─────────────────────────────────────────────────────────────┐
│ 向量数据库生态 │
├──────────────┬──────────────┬──────────────┬────────────────┤
│ 专用向量DB │ 云托管服务 │ 传统DB扩展 │ 向量计算库 │
├──────────────┼──────────────┼──────────────┼────────────────┤
│ Milvus │ Pinecone │ pgvector │ FAISS (Meta) │
│ Weaviate │ Zilliz Cloud│ Redis Stack │ Annoy (Spotify)│
│ Qdrant │ Supabase │ Elasticsearch│ ScaNN (Google) │
│ Chroma │ PlanetScale │ ClickHouse │ hnswlib │
└──────────────┴──────────────┴──────────────┴────────────────┘
2.2 主流产品详解
Milvus —— 开源向量数据库的标杆
- 类型:开源分布式向量数据库
- 开发语言:Go + C++
- 部署方式:Docker 单机 / K8s 集群 / Zilliz Cloud 托管
- 核心优势:
- 支持多种索引(IVF_FLAT、IVF_SQ8、HNSW、DISKANN 等)
- 支持标量过滤 + 向量搜索混合查询
- 支持分区、副本、容灾
- 社区活跃,文档完善
- 适用场景:中大型生产环境、需要高可用和可扩展性
- GitHub Stars:30k+
Pinecone —— 最简单的全托管方案
- 类型:全托管云服务(不开源)
- 部署方式:纯 SaaS,无需部署
- 核心优势:
- 零运维,开箱即用
- 自动扩缩容
- 与 LangChain 深度集成
- 适用场景:快速原型、不想运维的团队
- 缺点:数据必须上云,成本随数据量增长
Weaviate —— 内置向量化能力
- 类型:开源向量数据库
- 开发语言:Go
- 核心优势:
- 内置 vectorizer(可直接传文本,自动 embedding)
- 支持多模态(文本、图片)
- GraphQL API
- 适用场景:需要端到端向量化流程的项目
Qdrant —— Rust 编写的高性能方案
- 类型:开源向量数据库
- 开发语言:Rust
- 核心优势:
- 性能极高(Rust 的优势)
- 支持丰富的过滤条件
- 支持 payload(附加元数据)
- 提供云服务
- 适用场景:对性能要求极高的场景
Chroma —— 最适合入门和原型开发
- 类型:开源轻量级向量数据库
- 开发语言:Python
- 核心优势:
- 极简 API,几行代码搞定
- 内嵌模式,无需独立部署
- 与 LangChain、LlamaIndex 无缝集成
- 适用场景:本地开发、快速原型、小规模应用
- 缺点:不适合大规模生产环境
pgvector —— PostgreSQL 的向量扩展
- 类型:PostgreSQL 扩展插件
- 核心优势:
- 如果你已经在用 PostgreSQL,零额外基础设施
- 向量搜索 + SQL 查询一体化
- 支持 IVFFlat、HNSW 索引
- 适用场景:已有 PG 基础设施、数据量中等(百万级以内)
FAISS —— Meta 的向量检索库
- 类型:向量检索库(不是数据库)
- 开发语言:C++(Python 绑定)
- 核心优势:
- 极致性能,支持 GPU 加速
- 索引类型最丰富
- 适合研究和自定义场景
- 缺点:没有持久化、没有分布式、需要自己封装
2.3 选型对比表
| 产品 | 部署方式 | 语言 | 最适合场景 | 学习成本 | 社区活跃度 | 生产就绪 |
|---|---|---|---|---|---|---|
| Milvus | Docker/K8s/云 | Go+C++ | 中大型生产 | 中 | ⭐⭐⭐⭐⭐ | ✅ |
| Pinecone | 纯 SaaS | - | 快速上线 | 低 | ⭐⭐⭐⭐ | ✅ |
| Weaviate | Docker/云 | Go | 多模态场景 | 中 | ⭐⭐⭐⭐ | ✅ |
| Qdrant | Docker/云 | Rust | 高性能需求 | 中 | ⭐⭐⭐⭐ | ✅ |
| Chroma | 内嵌/Docker | Python | 开发原型 | 极低 | ⭐⭐⭐ | ⚠️ 小规模 |
| pgvector | PG 扩展 | C | 已有 PG 基础设施 | 低 | ⭐⭐⭐⭐ | ✅ |
| FAISS | 库引用 | C++ | 研究/自定义 | 中 | ⭐⭐⭐⭐⭐ | 需封装 |
2.4 选型决策树
你的场景是什么?
│
├── 快速原型/学习/本地开发
│ └── → Chroma(最简单)或 FAISS(性能好)
│
├── 已有 PostgreSQL
│ └── → pgvector(零额外成本)
│
├── 不想运维,只要结果
│ └── → Pinecone(全托管)
│
├── 中大型生产环境
│ ├── 需要分布式 → Milvus
│ ├── 需要极致性能 → Qdrant
│ └── 需要多模态 → Weaviate
│
└── 超大规模(亿级+)
└── → Milvus Cluster 或 Zilliz Cloud
第三章:快速上手(Chroma)
Chroma 是最适合入门的向量数据库,不需要任何部署,pip install 就能用。
3.1 安装
pip install chromadb
3.2 基本用法
import chromadb
# 1. 创建客户端(内存模式,数据不持久化)
client = chromadb.Client()
# 2. 创建一个集合(类似关系数据库的"表")
collection = client.create_collection(name="my_docs")
# 3. 添加文档
# Chroma 会自动帮你做 embedding(默认用 all-MiniLM-L6-v2)
collection.add(
documents=[
"红烧肉是一道经典的中国家常菜",
"量子力学是物理学的一个分支",
"番茄炒蛋是最简单的家常菜",
"相对论由爱因斯坦提出",
],
ids=["doc1", "doc2", "doc3", "doc4"],
metadatas=[
{"category": "cooking"},
{"category": "physics"},
{"category": "cooking"},
{"category": "physics"},
]
)
# 4. 查询——找和"家常菜"最相似的文档
results = collection.query(
query_texts=["怎么做家常菜"],
n_results=2 # 返回最相似的 2 个
)
print(results)
# 输出:
# {
# 'documents': [['番茄炒蛋是最简单的家常菜', '红烧肉是一道经典的中国家常菜']],
# 'distances': [[0.35, 0.52]],
# 'metadatas': [[{'category': 'cooking'}, {'category': 'cooking'}]]
# }
3.3 持久化存储
# 数据保存到磁盘
client = chromadb.PersistentClient(path="./chroma_db")
# 下次启动时自动加载已有数据
collection = client.get_collection(name="my_docs")
3.4 带过滤条件的查询
# 只在 cooking 类别中搜索
results = collection.query(
query_texts=["好吃的菜"],
n_results=2,
where={"category": "cooking"} # 标量过滤
)
3.5 手动指定向量
如果你已经有 embedding(比如用 OpenAI 生成的),可以直接传入:
# 手动传入向量
collection.add(
embeddings=[[0.1, 0.2, 0.3, ...], [0.4, 0.5, 0.6, ...]],
documents=["文档1", "文档2"],
ids=["id1", "id2"]
)
# 查询时也传入向量
results = collection.query(
query_embeddings=[[0.1, 0.2, 0.3, ...]],
n_results=2
)
第四章:进阶用法(Milvus)
当你需要生产级别的向量数据库时,Milvus 是最主流的选择。
4.1 Docker 部署
# 拉取并启动 Milvus 单机版(Standalone)
docker compose -f milvus-standalone-docker-compose.yml up -d
milvus-standalone-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
- 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_data
command: minio server /minio_data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
standalone:
image: milvusdb/milvus:v2.4.0
command: ["milvus", "run", "standalone"]
environment:
ETCD_ENDPOINTS: etcd:2379
MINIO_ADDRESS: minio:9000
volumes:
- milvus_data:/var/lib/milvus
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"]
interval: 30s
start_period: 90s
timeout: 20s
retries: 3
ports:
- "19530:19530"
- "9091:9091"
depends_on:
- "etcd"
- "minio"
volumes:
etcd_data:
minio_data:
milvus_data:
启动后访问 http://localhost:9091/healthz 确认服务正常。
4.2 Python SDK 基本用法
pip install pymilvus
from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType, utility
# 1. 连接 Milvus
connections.connect("default", host="localhost", port="19530")
# 2. 定义 Schema
fields = [
FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True),
FieldSchema(name="title", dtype=DataType.VARCHAR, max_length=512),
FieldSchema(name="category", dtype=DataType.VARCHAR, max_length=64),
FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=1536),
]
schema = CollectionSchema(fields, description="文档向量集合")
# 3. 创建 Collection
collection = Collection("documents", schema)
# 4. 创建索引(HNSW 索引,适合高召回率场景)
index_params = {
"metric_type": "COSINE", # 余弦相似度
"index_type": "HNSW",
"params": {
"M": 16, # 每个节点的最大连接数
"efConstruction": 200 # 构建时的搜索宽度
}
}
collection.create_index("embedding", index_params)
# 5. 插入数据
import random
data = [
["红烧肉的做法", "番茄炒蛋的做法", "量子力学入门", "相对论简述"],
["cooking", "cooking", "physics", "physics"],
[[random.random() for _ in range(1536)] for _ in range(4)] # 模拟向量
]
collection.insert(data)
collection.flush()
# 6. 加载到内存(查询前必须)
collection.load()
# 7. 向量搜索
search_params = {"metric_type": "COSINE", "params": {"ef": 100}}
# 用一个模拟查询向量
query_vector = [[random.random() for _ in range(1536)]]
results = collection.search(
data=query_vector,
anns_field="embedding",
param=search_params,
limit=3,
output_fields=["title", "category"] # 返回附加字段
)
for hits in results:
for hit in hits:
print(f"ID: {hit.id}, Score: {hit.score:.4f}, Title: {hit.entity.get('title')}")
4.3 带标量过滤的向量搜索
# 只搜索 cooking 类别的文档
results = collection.search(
data=query_vector,
anns_field="embedding",
param=search_params,
limit=3,
expr='category == "cooking"', # 标量过滤表达式
output_fields=["title", "category"]
)
4.4 常用索引类型对比
| 索引类型 | 原理 | 构建速度 | 查询速度 | 召回率 | 内存占用 | 适用场景 |
|---|---|---|---|---|---|---|
| FLAT | 暴力搜索 | 最快 | 最慢 | 100% | 最高 | 小数据集(<10万) |
| IVF_FLAT | 倒排索引 + 暴力 | 快 | 中 | 高 | 高 | 中等数据集 |
| IVF_SQ8 | 倒排 + 标量量化 | 中 | 中 | 中 | 低 | 内存受限 |
| HNSW | 图索引 | 慢 | 最快 | 很高 | 高 | 高召回率场景 |
| DISKANN | 磁盘图索引 | 慢 | 中 | 高 | 低 | 超大数据集 |
选型建议:
- 数据量 < 10 万:用 FLAT(暴力搜索就够)
- 需要高召回率:用 HNSW
- 内存紧张:用 IVF_SQ8
- 数据量超大(亿级+):用 DISKANN
第五章:如何部署
5.1 本地开发(零部署)
Chroma(内嵌模式):
import chromadb
client = chromadb.PersistentClient(path="./my_db")
# 完毕,不需要任何服务器
FAISS(纯库):
import faiss
import numpy as np
d = 128 # 向量维度
nb = 100000 # 数据量
index = faiss.IndexFlatL2(d) # L2 距离的暴力索引
vectors = np.random.random((nb, d)).astype('float32')
index.add(vectors) # 插入向量
# 保存到磁盘
faiss.write_index(index, "my_index.faiss")
# 加载
index = faiss.read_index("my_index.faiss")
# 搜索
query = np.random.random((1, d)).astype('float32')
D, I = index.search(query, k=5) # 返回距离和索引
print(f"最近的 5 个向量索引: {I[0]}")
5.2 Docker 单机部署
Milvus Standalone(见第四章 4.1)
Qdrant:
docker run -p 6333:6333 -p 6334:6334 \
-v $(pwd)/qdrant_storage:/qdrant/storage \
qdrant/qdrant
Weaviate:
docker run -p 8080:8080 \
-e AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED=true \
-e PERSISTENCE_DATA_PATH=/var/lib/weaviate \
semitechnologies/weaviate:latest
5.3 集群部署(Milvus)
生产环境推荐使用 Milvus Operator 部署到 Kubernetes:
# 1. 安装 Milvus Operator
kubectl apply -f https://raw.githubusercontent.com/milvus-io/milvus-operator/main/deploy/manifests/deployment.yaml
# 2. 创建 Milvus Cluster
cat <<EOF | kubectl apply -f -
apiVersion: milvus.io/v1beta1
kind: Milvus
metadata:
name: my-milvus
spec:
mode: cluster
components:
proxy:
serviceType: LoadBalancer
config:
common:
storageType: minio
dependencies:
etcd:
inCluster:
deletionPolicy: Delete
pvcDeletion: true
storage:
inCluster:
deletionPolicy: Delete
pvcDeletion: true
pulsar:
inCluster:
deletionPolicy: Delete
pvcDeletion: true
EOF
5.4 全托管云服务
如果不想自己运维,可以选择:
| 服务 | 提供方 | 特点 |
|---|---|---|
| Zilliz Cloud | Milvus 官方 | 和 Milvus 完全兼容,全球多区域 |
| Pinecone | Pinecone Inc. | 最简单的 SaaS,免费额度 |
| Supabase | Supabase | PG + pgvector,开发者友好 |
| Weaviate Cloud | Weaviate | 托管 Weaviate |
下篇预告
到这里,我们已经搞定了向量数据库的基础认知、产品选型、代码上手和部署方案。你已经能在本地跑通一个完整的向量搜索 demo 了。
但"能跑"和"能用在生产环境"之间,还隔着一道不小的鸿沟:
- 索引参数怎么调才能兼顾速度和准确率?
- 100 万条 1536 维的向量,服务器内存到底要多大?
- 数据怎么备份?挂了怎么办?
- 怎么和 LangChain Agent 配合,搭建一个真正的 RAG 问答系统?
这些问题,我们留到下篇一一解决。
本文为系列上篇,完整系列:
- 上篇:概念、选型与快速上手(本文)
- 下篇:生产实践与 Agent 集成
更多推荐
所有评论(0)