作者:唐璜Taro |AI 教程系列 | 适合读者:零基础开发者
阅读时间:约 25 分钟
系列:本文为下篇,上篇见 → 《向量数据库从入门到生产(上):概念、选型与快速上手》


前情回顾

在上篇中,我们完成了以下内容:

  1. 理解了向量数据库的核心概念——向量、Embedding、相似度搜索
  2. 对比了 7 款主流向量数据库,给出了选型决策树
  3. 用 Chroma 从零跑通了第一个向量搜索 demo
  4. 用 Milvus 学习了生产级的 SDK 用法和索引类型
  5. 掌握了 4 种部署方式:本地、Docker、K8s 集群、云托管

如果你还没读过上篇,建议先去阅读:上篇入口

本篇我们进入实战深水区——把向量数据库真正用到生产环境里。


在这里插入图片描述

目录


第六章:生产环境最佳实践

6.1 索引选择与调参

上篇我们介绍了各种索引类型,这里给出生产环境的具体调参建议:

# 生产环境推荐 HNSW 索引
index_params = {
    "metric_type": "COSINE",
    "index_type": "HNSW",
    "params": {
        "M": 32,              # 生产环境建议 16-64
        "efConstruction": 256  # 构建质量,越大越好但越慢
    }
}

# 搜索时的 ef 参数(影响召回率和速度的平衡)
search_params = {
    "metric_type": "COSINE",
    "params": {"ef": 128}  # ef 越大召回率越高,但越慢
}

调参原则

  • M 越大 → 图越密集 → 召回率越高 → 内存越大
  • efConstruction 越大 → 索引质量越好 → 构建越慢
  • ef(搜索时)≥ top_k,一般设为 top_k 的 2-10 倍

实际调参经验

场景 M efConstruction ef 效果
快速原型 8 100 32 快,召回率一般
均衡模式 16 200 64 速度和召回率平衡
高精度 32 256 128 召回率高,稍慢
极致精度 64 512 256 召回率最高,较慢

6.2 数据分片与分区

当数据量增长到千万级,单个 Collection 的查询性能会下降。分区可以把数据按业务维度切分,缩小搜索范围:

# 按业务维度分区(如按年份)
collection = Collection("documents", schema)

# 创建分区
collection.create_partition("2023")
collection.create_partition("2024")
collection.create_partition("2025")

# 插入到指定分区
collection.insert(data, partition_name="2025")

# 只在特定分区搜索
results = collection.search(
    data=query_vector,
    anns_field="embedding",
    param=search_params,
    limit=5,
    partition_names=["2024", "2025"]  # 只搜最近两年
)

分区策略建议

分区维度 适用场景 示例
时间 数据有时效性 按年/月分区
业务线 多业务共享集群 按产品线分区
数据类型 不同类型用不同索引 按文档/图片分区

6.3 批量操作

生产环境一定要避免逐条操作:

# ❌ 逐条插入(慢,每条都走一次网络往返)
for doc in documents:
    collection.insert([doc])

# ✅ 批量插入(快,减少网络开销)
batch_size = 1000
for i in range(0, len(documents), batch_size):
    batch = documents[i:i + batch_size]
    collection.insert(batch)

批量操作性能对比(10 万条数据,1536 维向量):

方式 耗时 吞吐量
逐条插入 ~30 分钟 ~55 条/秒
批量 100 ~3 分钟 ~555 条/秒
批量 1000 ~30 秒 ~3333 条/秒
批量 5000 ~15 秒 ~6666 条/秒

6.4 监控关键指标

生产环境需要监控的核心指标:

指标 含义 告警阈值建议
查询延迟 P99 99% 的查询耗时 > 100ms
QPS 每秒查询数 根据业务设定
内存使用率 节点内存占用 > 85%
磁盘使用率 存储空间占用 > 80%
索引构建状态 索引是否就绪 未就绪
节点健康状态 各节点是否存活 有节点宕机

Milvus 自带 Prometheus 指标暴露,配合 Grafana 即可搭建监控面板:

# Milvus 指标端点
http://<milvus-host>:9091/metrics

6.5 安全实践

# Milvus 开启认证
connections.connect(
    "default",
    host="localhost",
    port="19530",
    user="admin",
    password="your_secure_password"
)

其他安全措施:

  • 网络隔离:向量数据库不应暴露到公网,使用 VPC/内网访问
  • TLS 加密:生产环境必须开启 TLS
  • RBAC 权限控制:不同服务使用不同账号
  • 数据加密:静态数据加密(磁盘级或应用级)

第七章:数据如何存储

7.1 向量数据的存储结构

一个向量记录在存储中通常包含:

┌──────────────────────────────────────────────────┐
│                   一条向量记录                     │
├────────────┬─────────────┬───────────────────────┤
│   ID       │  标量字段    │     向量数据           │
│  (8 bytes) │  (可变长度)  │  (dim × 4 bytes)      │
│  int64     │  title, tag  │  float32[]            │
├────────────┼─────────────┼───────────────────────┤
│   1001     │ "红烧肉..."  │ [0.23, -0.45, ...]    │
└────────────┴─────────────┴───────────────────────┘

7.2 存储开销计算

原始向量存储

单个向量大小 = 维度 × 4 字节(float32)
维度 单个向量 100 万个 1 亿个
128 512 B 488 MB 47.7 GB
768 3 KB 2.9 GB 286 GB
1536 6 KB 5.7 GB 572 GB

索引额外开销

索引类型 额外存储倍数 说明
FLAT 1x 无额外开销
IVF_FLAT 1.1-1.2x 倒排列表
IVF_SQ8 0.3x 量化压缩
HNSW 1.5-2x 图结构
DISKANN 1.2x 磁盘图

总存储估算公式

总内存 ≈ 原始向量大小 × 索引倍数 + 标量字段 + 系统开销(20%)

举例:100 万个 1536 维向量,HNSW 索引:

5.7 GB × 1.8(HNSW 倍数)+ 0.5 GB(标量)+ 20% 系统开销
≈ 10.3 GB + 0.5 GB + 2.2 GB ≈ 13 GB

7.3 持久化策略

不同向量数据库的持久化方式:

产品 存储后端 持久化方式
Milvus MinIO/S3 + etcd 自动持久化,支持对象存储
Chroma 本地文件系统 SQLite + Parquet 文件
Qdrant 本地文件系统 WAL + 段文件
Weaviate 本地文件系统 自定义 LSM 树
FAISS 无内置持久化 手动 faiss.write_index()

7.4 数据备份与恢复

# Milvus:使用 collection 的快照功能
# 或直接备份 etcd + MinIO 数据

# Chroma:直接复制持久化目录
import shutil
shutil.copytree("./chroma_db", "./chroma_db_backup")

# FAISS:保存索引文件
import faiss
faiss.write_index(index, "backup_index.faiss")

生产环境备份策略

策略 频率 适用场景
全量备份 每天/每周 数据量不大,可接受一定数据丢失
增量备份 每小时 数据更新频繁
实时复制 实时 关键业务,零数据丢失

第八章:服务器要求

8.1 硬件资源需求公式

内存
最低内存 = 向量数据量 × 维度 × 4 字节 × 索引倍数
推荐内存 = 最低内存 × 1.5(留 buffer)
CPU
  • 向量搜索是 CPU 密集型操作
  • 核心数越多,并发查询能力越强
  • 建议:生产环境至少 8 核
磁盘
  • SSD 优于 HDD(随机读写性能差距 100 倍)
  • Milvus 等依赖对象存储的需要考虑网络磁盘性能
  • 建议:NVMe SSD
GPU(可选)
  • FAISS 支持 GPU 加速,速度提升 5-10 倍
  • Milvus GPU 版本(Beta)支持 GPU 索引
  • 适合超大规模或低延迟场景

8.2 不同规模的配置建议

万级数据(开发/测试)
CPU: 2 核
内存: 4 GB
磁盘: 20 GB SSD
推荐产品: Chroma(内嵌模式)/ FAISS
十万级数据(小型应用)
CPU: 4 核
内存: 8 GB
磁盘: 100 GB SSD
推荐产品: Chroma / pgvector / Qdrant 单机
百万级数据(中型应用)
CPU: 8-16 核
内存: 32-64 GB
磁盘: 500 GB SSD
推荐产品: Milvus Standalone / Qdrant / Weaviate
千万级数据(大型应用)
CPU: 32 核+
内存: 128 GB+
磁盘: 2 TB SSD
推荐产品: Milvus Cluster(3+ 节点)
亿级数据(超大规模)
CPU: 多节点集群
内存: 512 GB+(分布式)
磁盘: 分布式存储
推荐产品: Milvus Cluster(多分片)/ Zilliz Cloud
特殊处理: 使用 DISKANN 索引减少内存占用

8.3 操作系统建议

要求 推荐
操作系统 Ubuntu 20.04+ / CentOS 7+
内核版本 5.x+
Docker 20.10+
Kubernetes 1.22+(集群部署)

第九章:与 Agent 配合使用

这一章是本篇的重点,也是向量数据库最有价值的应用场景——让 AI Agent 拥有"长期记忆"。

9.1 RAG 流程回顾

用户提问
   │
   ▼
┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐
│  文档加载  │ →  │  文本分割  │ →  │  向量化   │ →  │  存入向量DB │
│  (Loader) │    │ (Splitter)│    │(Embedding)│    │           │
└──────────┘    └──────────┘    └──────────┘    └──────────┘
                                                       │
                                                       ▼
┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐
│  生成回答  │ ←  │  LLM 推理  │ ←  │  构建提示  │ ←  │  相似度搜索 │
│           │    │ (Agent)  │    │(Prompt)  │    │ (Retriever)│
└──────────┘    └──────────┘    └──────────┘    └──────────┘

向量数据库在 RAG 中扮演的角色:把"知识"变成 LLM 可以随时检索的"外部记忆"

9.2 LangChain + Chroma 完整示例

pip install langchain langchain-community langchain-openai chromadb
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain.chains import RetrievalQA

# 1. 加载文档
loader = TextLoader("my_knowledge_base.txt", encoding="utf-8")
documents = loader.load()

# 2. 分割文本
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50,
    separators=["\n\n", "\n", "。", "!", "?", ",", " "]
)
docs = text_splitter.split_documents(documents)
print(f"分割成 {len(docs)} 个文档块")

# 3. 向量化并存入 Chroma
embeddings = OpenAIEmbeddings()  # 使用 OpenAI 的 embedding 模型
vectorstore = Chroma.from_documents(
    documents=docs,
    embedding=embeddings,
    persist_directory="./chroma_db"
)

# 4. 创建检索器
retriever = vectorstore.as_retriever(
    search_type="similarity",  # 相似度搜索
    search_kwargs={"k": 3}     # 返回最相似的 3 个
)

# 5. 创建 QA 链
llm = ChatOpenAI(model="gpt-4", temperature=0)
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",        # 把检索到的文档拼接后传给 LLM
    retriever=retriever,
    return_source_documents=True
)

# 6. 提问
result = qa_chain.invoke({"query": "红烧肉怎么做?"})
print(f"回答:{result['result']}")
print(f"参考文档:{[doc.page_content[:50] for doc in result['source_documents']]}")

9.3 LangChain + Milvus 完整示例

pip install langchain langchain-community langchain-openai pymilvus
from langchain_community.vectorstores import Milvus
from langchain_openai import OpenAIEmbeddings
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI

# 1. 连接 Milvus 并创建向量存储
embeddings = OpenAIEmbeddings()

vectorstore = Milvus.from_documents(
    documents=docs,  # 上面分割好的文档
    embedding=embeddings,
    connection_args={"host": "localhost", "port": "19530"},
    collection_name="knowledge_base",
    index_params={"metric_type": "COSINE", "index_type": "HNSW", "params": {"M": 16, "efConstruction": 256}},
    search_params={"metric_type": "COSINE", "params": {"ef": 128}}
)

# 2. 创建 Agent
from langchain.agents import AgentExecutor, create_react_agent
from langchain.tools import Tool
from langchain import hub

# 把向量检索包装成一个 Tool
def search_knowledge_base(query: str) -> str:
    docs = vectorstore.similarity_search(query, k=3)
    return "\n\n".join([doc.page_content for doc in docs])

search_tool = Tool(
    name="knowledge_search",
    func=search_knowledge_base,
    description="搜索知识库,当需要查找内部文档、产品信息、技术规范时使用"
)

# 3. 创建 ReAct Agent
prompt = hub.pull("hwchase17/react")
llm = ChatOpenAI(model="gpt-4", temperature=0)

agent = create_react_agent(llm, [search_tool], prompt)
agent_executor = AgentExecutor(agent=agent, tools=[search_tool], verbose=True)

# 4. 运行
response = agent_executor.invoke({"input": "我们公司的退货政策是什么?"})
print(response["output"])

9.4 Agent 使用向量数据库的 4 种模式

模式一:直接检索(最常用)

最简单的模式,每次用户提问都先检索知识库,再把结果交给 LLM 生成回答。

用户问题 → 向量搜索 → 搜索结果 + 问题 → LLM → 回答

适用场景:FAQ 问答、文档检索、客服机器人。

模式二:Agent 自主决定是否检索

Agent 会先判断用户的问题是否需要查询知识库。如果是一般性对话(如"你好"),直接回答;如果涉及专业知识,再去搜索。

用户问题 → Agent 思考 → 判断需要搜索 → 向量搜索 → 综合回答
                       → 判断不需要 → 直接回答

适用场景:混合对话场景(既有闲聊又有专业问答)。

模式三:多轮检索

Agent 搜索一次后发现信息不够,自动换关键词再搜一次,直到获得足够的上下文。

用户问题 → Agent 第一次搜索 → 发现信息不足 → 第二次搜索(换关键词)→ 综合回答

适用场景:复杂问题、需要跨文档综合信息。

模式四:多知识库路由

Agent 根据问题类型,判断应该搜索哪个知识库。

用户问题 → Agent 判断属于哪个知识库 → 搜索对应库 → 回答
         ├── 技术文档库
         ├── 产品手册库
         └── FAQ 库

适用场景:企业内部多个知识库、多业务线。

9.5 实际应用场景

场景 说明 推荐方案
企业知识库问答 员工问公司制度、流程 RAG + Chroma/Milvus
客服机器人 回答产品问题、退换货政策 Agent + 向量搜索 + 工具调用
代码助手 基于项目代码回答问题 RAG + 代码 embedding
法律/医疗检索 检索专业文档辅助决策 高精度 RAG + 过滤条件
推荐系统 “看了这个还看了…” 向量相似度 + 协同过滤

第十章:总结与选型建议

10.1 核心知识点回顾

向量数据库的本质
├── 存储:把 embedding 向量高效存储
├── 索引:用 ANN 算法加速相似度搜索
├── 查询:支持 Top-K 相似度搜索 + 标量过滤
└── 应用:语义搜索、RAG、推荐系统

10.2 选型决策树(终版)

                        你的需求是什么?
                              │
              ┌───────────────┼───────────────┐
              ▼               ▼               ▼
          学习/原型        小型生产         中大型生产
              │               │               │
              ▼               ▼               ▼
          Chroma          pgvector        Milvus
         (零部署)       (已有PG时)       (首选方案)
              │               │               │
              └─── 不想运维 ───┘               │
                      │                       │
                      ▼                       ▼
                  Pinecone              需要极致性能?
                                           │
                              ┌────────────┼────────────┐
                              ▼            ▼            ▼
                            Qdrant     Weaviate    Zilliz Cloud
                           (Rust)    (多模态)     (Milvus 云)

10.3 推荐学习路径

入门阶段(1-2 天)
├── 理解 embedding 和向量的概念
├── 用 Chroma 跑通第一个 RAG demo
└── 理解 chunk_size 和 overlap 的影响

进阶阶段(1-2 周)
├── 部署 Milvus 单机版
├── 对比不同索引类型的效果
├── 学习标量过滤 + 向量搜索
└── 集成 LangChain 构建 Agent

生产阶段(1-2 月)
├── Milvus Cluster 部署与运维
├── 索引调参与性能优化
├── 监控告警体系建设
├── 数据备份与容灾方案
└── 安全加固(认证、加密、网络隔离)

10.4 常见踩坑清单

踩坑 说明 解决方案
chunk_size 太大 检索结果不精确 200-1000 字符,视场景调整
chunk_size 太小 丢失上下文 适当增大 overlap
embedding 模型不匹配 查询和文档用不同模型 统一使用同一个 embedding 模型
向量维度不一致 插入报错 确保所有向量维度相同
没有创建索引 查询极慢 插入数据前先创建索引
内存不足 服务 OOM 使用量化索引(IVF_SQ8)或 DISKANN
混合查询写法错误 过滤条件不生效 检查 expr 语法

10.5 一句话总结

初学者用 Chroma 入门,生产环境用 Milvus,不想运维用 Pinecone/Zilliz Cloud。记住:embedding 模型的选择比向量数据库的选择更重要。


附录:常用资源

资源 链接
Milvus 官方文档 https://milvus.io/docs
Chroma 官方文档 https://docs.trychroma.com
Qdrant 官方文档 https://qdrant.tech/documentation
Weaviate 官方文档 https://weaviate.io/developers/weaviate
Pinecone 官方文档 https://docs.pinecone.io
pgvector GitHub https://github.com/pgvector/pgvector
FAISS GitHub https://github.com/facebookresearch/faiss
LangChain 向量数据库集成 https://python.langchain.com/docs/integrations/vectorstores
MTEB Embedding 模型排行榜 https://huggingface.co/spaces/mteb/leaderboard

本文为系列下篇,完整系列:

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐