向量数据库与 Milvus:从原理到性能调优实践

随着大语言模型(LLM)和 AI 应用的爆发式增长,一种新型数据库悄然成为 AI 基础设施的核心组件----向量数据库(Vector Database)

传统数据库的局限

传统关系型数据库擅长精确匹配:WHERE name = 'Alice'。但面对以下场景时力不从心:

  • 以图搜图:找出"视觉上相似"的图片

  • 语义搜索:用一句话找出"含义相近"的文档

  • 推荐系统:找出"行为上相似"的用户

这类问题的本质是相似性搜索,而不是精确匹配。

向量与嵌入(Embedding)

AI 模型(如 BERT、CLIP、text-embedding-ada-002)可以将非结构化数据转化为高维浮点数向量,称为 Embedding:

 "今天天气真好" → [0.12, -0.87, 0.34, 0.91, ...]  # 768 维

语义相近的内容,其向量在空间中的距离也更近。相似性搜索就转化为了近似最近邻(ANN, Approximate Nearest Neighbor)搜索问题。

向量数据库的核心能力

 原始数据 → Embedding 模型 → 向量 → 向量数据库存储 → ANN 查询 → Top-K 结果
能力说明
高效 ANN 搜索亿级向量毫秒级返回
多种索引支持IVF、HNSW、DiskANN 等
标量过滤向量搜索 + 条件过滤组合查询
水平扩展分布式存储与查询

一、主流向量数据库对比

数据库定位特点
Milvus云原生分布式功能最全、生产级、支持超大规模
Pinecone全托管 SaaS开箱即用,不可自托管
Weaviate开源内置 vectorizer,GraphQL 接口
Qdrant开源 Rust 实现轻量高性能,适合中小规模
pgvectorPostgreSQL 插件现有 PG 用户的低成本选择
Chroma开源开发调试友好,不适合生产

二、Milvus 深度介绍

2.1 项目背景

Milvus 由 Zilliz 于 2019 年开源,是目前 GitHub Star 最多的向量数据库项目(35k+)。2021 年捐赠给 LF AI & Data Foundation,已成为 AI 基础设施领域的事实标准之一。

2.2 架构设计

Milvus 2.6 在 2.x 存算分离云原生架构基础上引入重要变更:将原先独立部署的三个协调节点 (RootCoord、QueryCoord、DataCoord)合并为单一组件 MixCoord,大幅降低了组件间 RPC 通信开销,简化了运维复杂度,同时保留了各协调器的内部逻辑边界。

 ┌─────────────────────────────────────────────┐
 │                   客户端                     │
 │         SDK (Python/Go/Java/Node.js)         │
 └──────────────────┬──────────────────────────┘
                    │ gRPC
 ┌──────────────────▼──────────────────────────┐
 │                 Proxy                       │
 │         负载均衡 · 鉴权 · 路由                 │
 └──────────────────┬──────────────────────────┘
                    │
 ┌──────────────────▼──────────────────────────┐
 │                 MixCoord                     │ ← 2.6 新增:统一协调层
 │ ┌────────────┬──────────────┬────────────┐ │
 │ │ RootCoord │ QueryCoord │ DataCoord │ │
 │ │ 元数据管理 │ 查询任务调度 │ 写入调度   │ │
 │ └────────────┴──────────────┴────────────┘ │
 └──────────┬───────────────────┬───────────────┘
            │                   │
 ┌──────────▼──────┐   ┌────────▼────────┐
 │   QueryNode     │   │   DataNode     │   ← 执行层(仍独立水平扩展)
 │ (向量搜索执行) │   │ (数据写入执行) │
 └─────────────────┘   └─────────────────┘
            ↕                   ↕
 ┌─────────────────────────────────────────────┐
 │           元数据存储(etcd)                   │
 ├─────────────────────────────────────────────┤
 │           对象存储(MinIO / S3)               │
 ├─────────────────────────────────────────────┤
 │           消息队列(Pulsar / Kafka / Woodpecker)│
 └─────────────────────────────────────────────┘

Milvus 2.6 新变化:引入自研 WAL 组件 Woodpecker,可替代 Pulsar/Kafka 作为轻量级消息队列,进一步减少外部依赖,降低部署复杂度。

各组件职责:

组件职责2.6 变化
Proxy请求入口,鉴权、路由、负载均衡无变化
MixCoord统一协调层,内含 RootCoord / QueryCoord / DataCoord新增,替代原三个独立 Coord
↳ RootCoord元数据管理(集合、分区、Schema)合并入 MixCoord
↳ QueryCoord查询任务调度,Segment 负载均衡合并入 MixCoord
↳ DataCoord写入任务调度,Segment 分配与 compaction合并入 MixCoord
QueryNode实际执行向量搜索(可水平扩展)无变化
DataNode实际执行数据写入(可水平扩展)无变化
etcd存储集群元数据(轻量级 KV)无变化
MinIO / S3持久化存储索引文件和原始数据无变化
Woodpecker自研轻量 WAL,可替代 Pulsar/Kafka2.6 新增

MixCoord 合并带来的收益:

  • 三个 Coord 之间的 RPC 调用变为进程内函数调用,延迟降低、吞吐提升

  • 减少需要独立运维的 Pod 数量,部署更简单

  • 元数据一致性更易保证,减少分布式事务复杂度

  • 执行层(QueryNode / DataNode)仍可独立水平扩展,弹性能力不受影响

2.3 核心概念

 Collection(集合)≈ 关系型数据库的 Table
    └── Schema(字段定义)
          ├── primary_key(必须)
          ├── vector field(向量字段,必须)
          └── scalar fields(标量字段,可选)
    └── Partition(分区,逻辑隔离)
          └── Segment(物理存储单元)
                ├── Growing Segment(写入中)
                └── Sealed Segment(已封存,可建索引)

2.4 索引类型选择

向量索引是 Milvus 性能的核心,按场景选择:

索引类型原理适用场景召回率
FLAT暴力穷举小数据量(<100万),精确召回100%
IVF_FLAT倒排量化中等规模,内存充足
IVF_SQ8量化压缩内存受限场景
HNSW图索引高 QPS,低延迟很高
DISKANN磁盘索引超大规模(百亿级),内存受限
IVF_PQ乘积量化极大规模,极低内存

经验法则:

  • 开发测试 → FLAT

  • 生产环境,QPS 优先 → HNSW

  • 生产环境,内存敏感 → IVF_SQ8DISKANN

2.5 距离度量方式

度量方式特点适用场景
L2(欧氏距离)值越小越相似图像、通用场景
IP(内积)值越大越相似需归一化,文本语义搜索
COSINE(余弦相似度)值越大越相似文本语义搜索(推荐)

三、快速上手示例

3.1 连接与创建集合

 from pymilvus import MilvusClient, DataType
 
 client = MilvusClient(
     uri="http://localhost:19530",
     token="root:Milvus"
 )
 
 schema = client.create_schema(auto_id=False, enable_dynamic_field=True)
 schema.add_field("id",        DataType.INT64,        is_primary=True)
 schema.add_field("embedding", DataType.FLOAT_VECTOR, dim=768)
 schema.add_field("text",      DataType.VARCHAR,      max_length=1000)
 
 index_params = client.prepare_index_params()
 index_params.add_index(
     field_name="embedding",
     index_type="HNSW",
     metric_type="COSINE",
     params={"M": 16, "efConstruction": 200}
 )
 
 client.create_collection(
     collection_name="my_docs",
     schema=schema,
     index_params=index_params
 )

3.2 插入数据

 import numpy as np
 
 data = [
    {
         "id": i,
         "embedding": np.random.rand(768).tolist(),
         "text": f"文档内容 {i}"
    }
     for i in range(10000)
 ]
 
 # 批量插入,推荐每批 1000~5000 条
 batch_size = 2000
 for i in range(0, len(data), batch_size):
     client.insert(collection_name="my_docs", data=data[i:i+batch_size])
 
 client.flush(collection_name="my_docs")

3.3 向量搜索

 query_vector = np.random.rand(768).tolist()
 
 results = client.search(
     collection_name="my_docs",
     data=[query_vector],
     limit=10,
     output_fields=["text"],
     search_params={"metric_type": "COSINE", "params": {"ef": 100}}
 )
 
 for hit in results[0]:
     print(f"id={hit['id']}, score={hit['distance']:.4f}, text={hit['entity']['text']}")

3.4 混合搜索(向量 + 标量过滤)

 results = client.search(
     collection_name="my_docs",
     data=[query_vector],
     filter="category == 'tech'",   # 标量过滤
     limit=10,
     output_fields=["text", "category"]
 )

四、性能调优要点

4.1 索引参数调优

 # HNSW 参数说明
 # M:               图的最大连接数,越大召回率越高,内存消耗越多(推荐 8~64)
 # efConstruction: 建索引时搜索深度,越大质量越高,建索引越慢(推荐 100~500)
 # ef:             查询时搜索深度,越大召回率越高,延迟越大(推荐 > limit)
 
 index_params.add_index(
     field_name="embedding",
     index_type="HNSW",
     metric_type="COSINE",
     params={"M": 16, "efConstruction": 200}      # 建索引时
 )
 
 search_params={"params": {"ef": 64}}             # 查询时

4.2 资源监控与火焰图

当出现查询延迟高、CPU 飙升等问题时,Milvus 各组件(包括 MixCoord、QueryNode、DataNode) 均在 9091 端口暴露 pprof 接口,可采集火焰图定位热点:

 # 对目标组件 pod 做端口转发
 kubectl port-forward -n milvus <querynode-pod> 9091:9091
 
 # 采集 30 秒 CPU profile(在问题复现期间执行)
 curl -o cpu.prof "http://localhost:9091/debug/pprof/profile?seconds=30"
 
 # 生成交互式火焰图,浏览器访问 http://localhost:8080 → View → Flame Graph
 go tool pprof -http=0.0.0.0:8080 cpu.prof

或用 go-torch 或 FlameGraph 生成 SVG

 # 安装 FlameGraph 工具
 git clone https://github.com/brendangregg/FlameGraph /opt/FlameGraph
 
 # 生成 SVG 火焰图
 go tool pprof -raw -output=cpu.txt cpu.prof
 /opt/FlameGraph/stackcollapse-go.pl cpu.txt | /opt/FlameGraph/flamegraph.pl > cpu.svg

其他常用 profile:

 curl -o heap.prof      "http://localhost:9091/debug/pprof/heap"       # 内存
 curl -o goroutine.prof "http://localhost:9091/debug/pprof/goroutine"  # goroutine 泄漏
 curl -o mutex.prof     "http://localhost:9091/debug/pprof/mutex"      # 锁竞争

4.3 常见性能问题排查

现象排查方向
查询 P99 延迟高QueryNode CPU profile,检查 ef 参数是否过大
写入吞吐低DataNode profile,检查批量大小和 flush 频率
内存持续增长heap profile,检查 Segment 是否正常 compact
goroutine 数量异常goroutine dump,排查泄漏
MixCoord 响应慢MixCoord CPU profile,检查元数据操作热点

五、典型应用场景

 RAG(检索增强生成)
  用户问题 → Embedding → Milvus 向量搜索 → 相关文档 → LLM 生成答案
 
 以图搜图
  上传图片 → CLIP Embedding → Milvus 搜索 → 相似图片列表
 
 推荐系统
  用户行为 → 用户向量 → Milvus 搜索 → 相似用户 → 协同过滤推荐
 
 异常检测
  实时数据 → Embedding → 与历史数据比较距离 → 距离超阈值则告警

六、总结

向量数据库解决了 AI 时代非结构化数据的相似性搜索难题。Milvus 凭借其云原生分布式架构、 丰富的索引支持和活跃的开源社区,已成为生产级向量数据库的首选方案。

Milvus 2.6 核心变化回顾:

特性说明
MixCoord三个协调节点合并为一,降低通信开销,简化运维
Woodpecker自研轻量 WAL,可替代 Pulsar/Kafka
执行层不变QueryNode / DataNode 仍独立水平扩展

通用最佳实践:

  • HNSW 索引适合大多数高 QPS 生产场景

  • 批量写入(1000~5000 条/批)显著提升写入吞吐

  • pprof + 火焰图是 Go 服务性能调优的标准手段

  • 合理设置 ef 参数平衡召回率与查询延迟


参考资料

Monthly Archives

Pages

Powered by Movable Type 9.1.1

About this Entry

This page contains a single entry by Cnangel published on June 4, 2026 7:29 PM.

Fedora44 升级体验 was the previous entry in this blog.

Find recent content on the main index or look in the archives to find all content.