milvus教程1: 从零开始理解向量数据库
什么是 Milvus?
Milvus 是一个开源的高性能向量数据库,专为 AI 应用的海量非结构化数据检索而设计。
想象一下:你想在几百万张图片中找到"与这张猫最相似的 100 张",或者在千万篇文档里搜索"与这段文字语义最接近的内容"——传统数据库做不到,而 Milvus 可以。
它把文本、图片、视频等非结构化数据转换成向量(一长串数字),然后通过高效的**近似最近邻搜索(ANNS)**算法,在亿级数据中毫秒级找到最相似的结果。
Milvus 用 Go 和 C++ 编写,支持 CPU/GPU 硬件加速,采用计算与存储分离的分布式架构,可以水平扩展到数十亿向量。同时也提供单机模式(Standalone)和Milvus Lite(pip install 即可用),一套 API 从小项目无缝切换到企业级。
想零配置体验?Zilliz Cloud ☁️ 是 Milvus 的全托管云服务,免费额度即可上手。
架构概览
下图展示了 Milvus 的完整代码架构,从用户请求到硬件加速,共 10 层:
flowchart TB
client(("Client"))
subgraph L1[" 接入层 · Access Layer "]
direction LR
proxy["Proxy · gRPC / REST 用户入口"]
main["cmd/main.go"]
tools["cmd/tools · binlog, config, datameta, migration"]
end
subgraph L2[" 协调层 · Coordination Layer "]
direction LR
rootcoord["RootCoord · DDL/DCL 元数据管理"]
querycoord["QueryCoordV2 · 查询调度 负载均衡"]
datacoord["DataCoord · 数据编排 Segment管理"]
end
subgraph L3[" 执行层 · Execution Nodes "]
direction LR
datanode["DataNode · 数据写入 InsertBuffer"]
querynode["QueryNodeV2 · 向量检索 标量过滤"]
streamingnode["StreamingNode · WAL CDC 复制"]
end
subgraph L4[" Go 公共层 · Shared Infrastructure "]
direction LR
pkg_kv["pkg/kv · KV 抽象 etdc/tikv"]
pkg_streaming["pkg/streaming · 流处理/消息队列"]
pkg_util["pkg/util · merr paramtable mlog metrics"]
end
subgraph L5[" CGo 桥接层 · FFI Bridge (extern C) "]
direction LR
cgo_tokenizer["tokenizer_c · 分词器API"]
cgo_tokenstream["token_stream_c · Token迭代"]
cgo_phrase["phrase_match_c · 短语匹配"]
cgo_segcore["segcore_c · Segment操作"]
end
subgraph L6[" C++ 核心引擎 · libmilvus_core "]
direction LR
cpp_segcore["segcore · Segment引擎"]
cpp_index["index · 索引管理"]
cpp_storage["storage · 存储引擎 文件IO"]
cpp_common["common · bson/json/类型"]
tantivy_raii["tantivy RAII · RustResult 生命周期"]
end
subgraph L7[" 外部引擎 · External Engines "]
direction LR
knowhere["Knowhere · FAISS/HNSW/IVF/DiskANN/GPU"]
milvus_storage["Milvus-Storage · Parquet/Avro/S3/GCS"]
end
subgraph L8[" Rust 全文引擎 · Tantivy "]
direction LR
rust_ffi["FFI Export · #[no_mangle] extern C"]
rust_tantivy["Tantivy Core · 倒排索引 BM25 Tokenizer链"]
end
subgraph L9[" Conan C++ 第三方依赖 "]
direction LR
c_rpc["protobuf 5.27 · gRPC 1.67 · libavrocpp 1.12"]
c_data["Arrow 17 · rocksdb 6.29 · librdkafka 1.9"]
c_base["folly · boost 1.83 · abseil · openssl 3.3 · nlohmann_json"]
c_cloud["aws-sdk-cpp · azure-sdk · google-cloud-cpp · libcurl"]
c_other["zstd · snappy · lz4 · zlib · openblas · onetbb · xsimd · re2 · geos · roaring · glog · prometheus-cpp · fmt"]
end
subgraph L10[" 运行时外部依赖 · Runtime Dependencies "]
direction LR
etcd_srv[("etcd · 元数据")]
pulsar_kafka[("Pulsar / Kafka · 消息队列")]
s3_storage[("S3 / Minio · 对象存储")]
end
client --> L1
L1 --> L2
L2 --> L3
L3 --> L4
L4 --> L5
L5 --> L6
L6 --> L7
L6 --> L8
L9 -.- L6
L9 -.- L7
L4 --> L10
%% ==================== 样式 ====================
classDef access fill:#3A7D44,stroke:#2A5C32,color:#fff,stroke-width:2px
classDef coord fill:#2C7873,stroke:#1F5C58,color:#fff,stroke-width:2px
classDef node fill:#1E88A8,stroke:#156D8A,color:#fff,stroke-width:2px
classDef go fill:#5B6C84,stroke:#445369,color:#fff,stroke-width:1.5px
classDef cgo fill:#D4850A,stroke:#A86508,color:#fff,stroke-width:2px
classDef cpp fill:#7B4B8A,stroke:#5E3770,color:#fff,stroke-width:2px
classDef ext fill:#6A4C93,stroke:#503873,color:#fff,stroke-width:2px
classDef rust fill:#C75B39,stroke:#9E4427,color:#fff,stroke-width:2px
classDef conan fill:#8FA3B0,stroke:#6B7E8B,color:#fff,stroke-width:1px
classDef runtime fill:#4A6FA5,stroke:#34527A,color:#fff,stroke-width:1.5px
classDef client fill:#2E5077,stroke:#1A3A5C,color:#fff,stroke-width:2px
class proxy,main,tools access
class rootcoord,querycoord,datacoord coord
class datanode,querynode,streamingnode node
class pkg_kv,pkg_streaming,pkg_util go
class cgo_tokenizer,cgo_tokenstream,cgo_phrase,cgo_segcore cgo
class cpp_segcore,cpp_index,cpp_storage,cpp_common,tantivy_raii cpp
class knowhere,milvus_storage ext
class rust_ffi,rust_tantivy rust
class c_rpc,c_data,c_base,c_cloud,c_other conan
class etcd_srv,pulsar_kafka,s3_storage runtime
class client client
各层通俗解释
L1 接入层 — “门面”
Proxy 是唯一对外的入口,用户通过 gRPC 或 REST API(端口 19530)连接。所有增删改查请求经过 Proxy 校验、分配时间戳后,路由到后端的协调层。
L2 协调层 — “大脑”
三个协调器分工协作:
| 组件 | 职责 | 一句话理解 |
|---|---|---|
| RootCoord | DDL/DCL——建集合、删集合、管理权限 | 数据库管理员 |
| QueryCoordV2 | 查询调度、负载均衡、Segment 在 QueryNode 上的分配 | 调度中心 |
| DataCoord | 数据编排——管理 Segment 状态、触发索引构建 | 数据管家 |
L3 执行层 — “干活的”
| 组件 | 职责 | 一句话理解 |
|---|---|---|
| DataNode | 接收写入请求,把数据持久化为 binlog | 写入流水线 |
| QueryNodeV2 | 执行向量检索和标量过滤,持有内存索引 | 搜索引擎 |
| StreamingNode | 处理 WAL 写入、CDC 复制 | 消息中转站 |
L4 Go 公共层 — “工具箱”
所有 Go 组件共享的基础库:pkg/kv(对接 etcd/TiKV)、pkg/streaming(流处理)、pkg/util(日志 mlog、错误 merr、配置 paramtable、监控 metrics)。
L5 CGo 桥接层 — “翻译官”
通过 extern "C" 接让 Go 调用 C++ 高性能代码(分词器、Token 迭代、短语匹配、Segment 操作)。
L6 C++ 核心引擎 — “发动机”
性能关键代码都在这里:Segment 列式存储引擎、索引管理、文件 I/O 存储引擎、以及 Rust Tantivy 的 RAII 生命周期管理。
L7 外部引擎 — “高效零件”
- Knowhere: 向量搜索执行引擎,封装了 FAISS、HNSW、DiskANN 等主流算法,同时支持 GPU 加速
- Milvus-Storage: 存储引擎,支持 Parquet/Avro 格式,对接 S3/GCS/Azure 对象存储
L8 Rust 全文引擎 — “搜索引擎”
- Tantivy Core: 用 Rust 实现的全文搜索引擎,提供倒排索引、BM25 相关性评分
- FFI Export: 通过
#[no_mangle] extern "C"导出接口供 C++ 调用
L9 C++ 第三方依赖 — “零件供应商”
通过 Conan 包管理器管理的 C++ 库:protobuf、gRPC、Arrow、RocksDB、AWS/Azure/GCP SDK、zstd/snappy/lz4 压缩库、OpenBLAS、Prometheus 等。
L10 运行时外部依赖 — “基础设施”
| 服务 | 用途 |
|---|---|
| etcd | 元数据存储(集合定义、节点状态等) |
| Pulsar / Kafka | 消息队列,用于组件间通信和 WAL |
| S3 / Minio | 对象存储,存放 binlog、索引文件等持久化数据 |
Milvus 核心特性
数据模型与组织
Collection (集合,相当于表)
├── Shard 0 ─── VChannel ──→ PChannel ──→ WAL (Pulsar/Kafka)
│ ├── Partition A (分区,可选,最多 1024 个)
│ │ ├── Segment Group (负载均衡和副本的基本单元)
│ │ │ ├── Segment (最小存储单元,列式布局)
│ │ │ └── Segment
│ │ └── Segment Group
│ └── Partition B
├── Shard 1
└── ...
- 每个 Collection 可包含最多 256 个字段,其中最多 10 个向量字段,向量维度上限 32768
- Shard 分片最多 16 个,用于并行写入
- 支持动态 Schema(无需预定义所有字段)
真实物理存储:纯列式(Columnar)布局
Milvus 在内存和磁盘上都采用纯列式存储——每个字段(列)的数据独立存放,完全不存"行"的概念。
为什么用列式?
- 向量搜索通常只访问 1~2 个向量列 + 少量标量列,列式意味着只读需要的列,大幅减少 I/O
- 列内数据同构(都是 float32 或都是 int64),有利于 SIMD 批量处理,一次 CPU 指令处理多个值
- 同一列数据高度相似,压缩率远高于行式
Segment 内部的 Chunk 分块结构:
每个 Segment 中,一个字段的数据被切割为固定大小的 Chunk(数据块),默认每个 Chunk 包含 32,768 行:
Segment (Sealed, 磁盘/mmap)
├── field_0 (pk: INT64)
│ ├── Chunk 0 → [32768 个 int64] (FixedWidthChunk)
│ ├── Chunk 1 → [32768 个 int64]
│ └── Chunk 2 → [1234 个 int64] (最后一个 Chunk 不满)
├── field_1 (title: VARCHAR)
│ ├── Chunk 0 → [null_bitmap | uint32_offsets[] | string_data]
│ └── ...
└── field_2 (embedding: FLOAT_VECTOR[128])
├── Chunk 0 → [32768 × 128 × 4 bytes] (FixedWidthChunk, dim=128)
└── ...
不同数据类型使用不同的 Chunk 实现:
| Chunk 类型 | 适用类型 | 内存布局 |
|---|---|---|
FixedWidthChunk |
INT/FLOAT 标量、密集向量 | [null_bitmap][element × N]——定长连续存储 |
StringChunk |
VARCHAR, JSON, GEOMETRY | [null_bitmap][uint32_offsets][string_data]——变长,偏移索引 |
ArrayChunk |
ARRAY | [null_bitmap][offset+len pairs][element_data] |
VectorArrayChunk |
向量数组 | [offset+len pairs][vector_data] |
SparseFloatVectorChunk |
稀疏向量 | [null_bitmap][offsets][index+value pairs] |
查询引擎如何读数据:
在 C++ 查询引擎(segcore)中,表达式求值时通过 Span<T> 类型化视图访问 Chunk 数据:
// 查询时获取 field_0 的第 3 个 Chunk
Span<int64_t> pk_data = segment->chunk_data<int64_t>(field_0, chunk_id=3);
// pk_data.data() → int64_t* 连续内存,可直接 SIMD 扫描
// pk_data[100] → 第 100 行的 pk 值
所有 Chunk 都支持 mmap——Sealed Segment 的列数据可通过 mmap 映射到进程地址空间,无需全部加载到内存。
Shard 分片与通道模型
Shard 是 Milvus 实现并行写入的核心机制。每个 Shard 对应一个 VChannel(虚拟通道):
Shard (分片) ←→ VChannel (虚拟通道)
多个 VChannel 共享 → PChannel (物理通道) → WAL 后端 (Pulsar/Kafka 的 topic/partition)
Shard 关系的两类通道:
| 通道类型 | 数量 | 说明 |
|---|---|---|
| PChannel (物理通道) | 固定 16 个(启动时确定) | 对应 WAL 后端的 topic partition,是物理资源 |
| VChannel (虚拟通道) | = Collection 的 Shard 数 | 属于某个 Collection,多个 Collection 的 VChannel 可共享同一 PChannel |
命名规则:<pchannel_name>_<collectionID>v<shardIndex>,例如 by-dev-rootcoord-dml_0_12345v0。
Shard 工作机制:
- 创建 Collection 时:用户指定
shards_num(默认 2,最多 16),RootCoord 从 PChannel 池中按最小负载策略分配 VChannel(internal/streamingcoord/server/balancer/channel/manager.go:393-409) - 写入数据时:Proxy 对每行数据的主键(PK)做哈希 → 模 Shard 数 → 路由到对应的 VChannel(
internal/proxy/util.go:2602-2635),因此同一 PK 的多次写入一定进入同一 Shard - 每个 VChannel 维护独立的 Growing Segment:一个 VChannel 同一时刻只有一个活跃的 Growing Segment 接收新数据(
internal/datacoord/segment_manager.go:307-369),数据绝不跨 Shard
插入请求(3000 行数据)
│
▼
Proxy: 对每行 PK 取哈希 → 分配到对应 VChannel
├── VChannel 0 → Growing Segment A (接收约 1/16 的数据) ──→ PChannel 0
├── VChannel 1 → Growing Segment B ──→ PChannel 1
├── VChannel 2 → Growing Segment C ──→ PChannel 0 (共享)
└── ...
Segment 的两种形态
| 形态 | 名称 | 状态 | 说明 |
|---|---|---|---|
| Growing | 生长段 | 可写 | 接收新插入的数据,数据在内存中(InsertRecord)。支持实时的 PK 去重和小型内存索引 |
| Sealed | 密封段 | 只读 | 数据已刷盘到对象存储,不可修改。QueryNode 加载索引后响应搜索请求 |
Growing → Sealed 的触发条件:
- 行数达到阈值(默认约 100 万行)
- 内存大小达到上限
- 手动调用
flush()API - 达到时间上限后由后台任务自动封存(Seal)
完整写入路径
一条数据从客户端插入到物理存储,经过:
Client (Python/Go SDK)
│ insert(data)
▼
Proxy
│ ① 校验数据合法性、分配时间戳
│ ② PK 哈希 → 按 Shard/VChannel 分包
│ ③ 列式格式打包 (msgpb.InsertDataVersion_ColumnBased)
▼
StreamingNode + WAL (Pulsar/Kafka)
│ ④ 写 WAL 保证持久性
│ ⑤ Shard 拦截器分配 Growing Segment
▼
DataNode
│ ⑥ 从 WAL 消费数据,写入 InsertBuffer(内存列式结构)
│ ⑦ Segment 达到条件后触发 Flush
▼
对象存储 (S3/MinIO)
⑧ Segment 持久化
- StorageV1 (旧): 每个字段一个 binlog 文件 (event 格式)
- StorageV2/V3 (新): Apache Parquet 列式文件 + Manifest 清单
│
▼
DataCoord
⑨ 更新 etcd 中的 Segment 元数据 (状态: Flushed)
⑩ 触发索引构建任务
关键代码位置:Proxy 分包(internal/proxy/msg_pack.go:30-102)、DataNode 写入(internal/flushcommon/writebuffer/insert_buffer.go)、Flush(internal/flushcommon/syncmgr/task.go:48-92)、Parquet 写入(internal/storagev2/packed/packed_writer_ffi.go)。
磁盘文件结构(Segment 持久化)
一个 Sealed Segment 在对象存储上的文件组成:
{bucket}/insert_log/{collID}/{partID}/{segID}/
├── {fieldID}/ ← 每个字段一个目录(列式分离)
│ ├── {logID} ← binlog 数据文件
│ └── {logID} ← 大 Segment 可能拆成多个 binlog
├── {fieldID}/
│ └── ...
└── (StorageV2/V3) _manifest.json ← Parquet 模式:Manifest 描述所有文件
{bucket}/delta_log/{collID}/{partID}/{segID}/
└── {logID} ← 删除记录(PK + 时间戳)
{bucket}/stats_log/{collID}/{partID}/{segID}/
└── {fieldID}/{logID} ← 每列的统计信息(便于查询优化)
与之对应的 etcd 元数据(SegmentInfo)记录以上所有文件的路径列表,QueryNode 据此加载。
数据类型
| 类别 | 类型 |
|---|---|
| 布尔 | BOOL |
| 整数 | INT8, INT16, INT32, INT64 |
| 浮点 | FLOAT, DOUBLE |
| 字符串 | VARCHAR(须指定 max_length) |
| JSON | JSON(支持路径索引) |
| 密集向量 | FLOAT_VECTOR, FLOAT16_VECTOR, BFLOAT16_VECTOR |
| 二值向量 | BINARY_VECTOR |
| 稀疏向量 | SPARSE_FLOAT_VECTOR |
| 整数向量 | INT8_VECTOR |
| 数组 | ARRAY |
| 空间 | GEOMETRY(支持 R-tree 索引) |
向量索引
密集向量
| 索引 | 算法基础 | 适用场景 |
|---|---|---|
FLAT |
暴力搜索 | 100%精确,小数据集(<100万) |
IVF_FLAT |
倒排文件 | 通用,平衡精度与速度 |
IVF_PQ |
乘积量化 | 内存敏感,高压缩率 |
IVF_SQ8 |
标量量化 | 精度折中,内存减半 |
IVF_RABITQ |
RaBitQ 量化 | 高效压缩 |
IVF_HNSW |
IVF+HNSW 混合 | 高精度、高召回 |
HNSW |
分层可导航小世界图 | 高精度,内存充足时首选 |
DISKANN |
基于磁盘的 ANN | 十亿级,突破内存限制 |
SCANN |
Google SCANN | 大规模低延迟 |
AUTOINDEX |
自动选择 | 不想手动调参时使用 |
GPU 加速索引
GPU_IVF_FLAT, GPU_IVF_PQ, GPU_CAGRA(NVIDIA CAGRA), GPU_BRUTE_FORCE
稀疏向量与标量索引
SPARSE_INVERTED_INDEX, SPARSE_WAND, MINHASH_LSH(去重);STL_SORT, Trie, INVERTED(Tantivy), BITMAP, RTREE, NGRAM
距离度量
L2(欧几里得), IP(内积), COSINE(余弦), HAMMING, JACCARD, MHJACCARD
搜索能力
- ANNS 向量搜索: 最核心——给定查询向量,返回最相似的 Top-K 结果
- 标量过滤: 支持
int64 > 100 AND varchar == "hello"等表达式 - 范围搜索: 返回距离在指定范围内的所有向量
- 混合搜索: 密集向量 + 稀疏向量 + 标量过滤同时执行,支持 Rerank
- 全文搜索: 基于 Tantivy 的 BM25 关键词检索
- 分组搜索: 按字段分组后每组返回 Top-K
- 分页搜索: 支持 Offset + Limit 分页
硬件加速
- CPU SIMD: AVX512、AVX2、AVX、SSE4_2 指令集自动检测启用
- GPU: NVIDIA CAGRA、GPU_IVF_FLAT、GPU_IVF_PQ、GPU_BRUTE_FORCE
- DiskANN: 基于磁盘的十亿级 ANN,用 NVMe SSD 突破内存上限
存储特性
- 对象存储: AWS S3、GCS、Azure Blob、MinIO
- 冷热分层: 热数据在内存/SSD,冷数据在对象存储,自动或手动迁移
- mmap: 向量、索引、标量、JSON 数据均支持内存映射
- 三重持久化: binlog(数据快照)+ WAL(操作日志)+ Index(索引文件)
多租户
支持四级隔离,适配从几百到百万级的租户管理:
| 级别 | 方式 | 适合 |
|---|---|---|
| Database | 独立的数据库 | 大客户独占(最多 64 个 DB) |
| Collection | 每个租户一个集合 | 中型租户 |
| Partition | 集合内分区 | 逻辑分组 |
| Partition Key | 基于字段值自动分区 | 海量租户(百万级) |
安全
- 强制用户认证: 用户名/密码
- TLS 加密: 外部和内部通信均可启用
- RBAC: 精细的角色访问控制
- API Key: API Key 认证方式
AI 集成
Milvus 内置对接了 13+ 种 Embedding/Rerank 提供商:
OpenAI、Azure OpenAI、HuggingFace、Bedrock、VertexAI、Gemini、Cohere、VoyageAI、Jina AI、DashScope(阿里云)、SiliconFlow、TEI、vLLM、Yandex Cloud
通过 pymilvus[model] 一行代码即可将文本/图片转为向量。
相比其他向量数据库的优势
| 维度 | Milvus | Pinecone | Weaviate | Qdrant | Chroma |
|---|---|---|---|---|---|
| 开源性 | Apache 2.0 | 闭源 SaaS | BSD-3 | Apache 2.0 | Apache 2.0 |
| 核心语言 | Go + C++ + Rust | — | Go | Rust | Python |
| 水平扩展 | ✅ 计算存储分离 K8s 原生 | ✅(SaaS 限) | ✅ | ✅ | ❌ 仅单机 |
| GPU 加速 | ✅ CAGRA + IVF | ❌ | 部分 | 部分 | ❌ |
| 全文搜索 | ✅ 原生 BM25 (Tantivy) | ❌ | ✅ BM25 | ❌ | ❌ |
| 冷热分层 | ✅ 原生 | 有限 | 有限 | ❌ | ❌ |
| 多租户 | 4 级隔离 | 集合级 | 集合级 | 集合级 | 集合级 |
| 十亿级规模 | ✅ DiskANN + 分布式 | ✅(SaaS) | ✅ | ✅ | ❌ |
| 自托管部署 | ✅ Docker/K8s | ❌ | ✅ | ✅ | ❌(仅嵌入式) |
| 轻量模式 | ✅ Milvus Lite (pip) | ❌ | ✅ Embedded | ❌ | ✅ 嵌入式 |
| 稀疏向量 | ✅ BM25/SPLADE/BGE-M3 | ❌ | ❌ | ❌ | ❌ |
| 安全 | ✅ Auth+TLS+RBAC | ✅ | ✅ | ✅ | 基础 |
| 托管服务 | ✅ Zilliz Cloud | 本身即 SaaS | ✅ Cloud | ✅ Cloud | ❌ |
Milvus 的核心优势
-
性能与可扩展性: 计算存储分离,读写节点独立扩缩容。Segment 副本机制保障高可用。Benchmark 工具可公开验证性能。
-
索引丰富度: 从暴力搜索(FLAT)到十亿级磁盘搜索(DiskANN),从 CPU SIMD 到 GPU CAGRA——一个平台覆盖所有规模。
-
独一无二的多模态搜索: 密集向量(语义)+ 稀疏向量(BM25 关键词)+ 标量过滤,一次查询混合执行并 Rerank。
-
成本优化: 冷热分层 + mmap + 对象存储,热数据高性能,冷数据低成本。
-
从轻量到企业: 同一套 API——从
pip install pymilvus[milvus-lite]到 Docker 到 K8s 集群,随时切换。 -
企业级安全: 少数同时提供完整安全特性(认证 + TLS + RBAC)且完全开源(Apache 2.0)的向量数据库。
进阶主题与生态
典型应用场景
| 场景 | 用到的能力 | 教程 |
|---|---|---|
| RAG(检索增强生成) | 向量搜索 + LLM | 教程 |
| 语义搜索 | 密集向量搜索 | 教程 |
| 以图搜图 | 图像向量化 + 相似搜索 | 教程 |
| 推荐系统 | 用户/物品向量匹配 | 教程 |
| 多模态搜索 | 文本 + 图片联合检索 | 教程 |
| Graph RAG | 知识图谱 + 向量搜索 | 教程 |
| 全文搜索 | BM25 + 密集向量混合 | 教程 |
生态集成
与主流 AI 框架的开箱即用集成:
# LangChain
from langchain_community.vectorstores import Milvus
# LlamaIndex
from llama_index.vector_stores.milvus import MilvusVectorStore
# HuggingFace
from pymilvus import model
embedding_fn = model.DefaultEmbeddingFunction()
# Haystack / Dify / DSPy / CrewAI / AutoGen 等也均支持
管理与监控工具:
| 工具 | 用途 |
|---|---|
| Attu | Web GUI 管理台 |
| Birdwatcher | 调试工具,分析元数据和 binlog |
| Prometheus + Grafana | 指标监控告警 |
| Milvus CDC | 跨集群数据同步 |
| Spark / Kafka / Airbyte | 数据管道 |
索引选择指南
数据量
├── < 100万 → FLAT(100% 精确,简单省心)
├── 100万-1亿 → IVF_SQ8 / HNSW / SCANN
│ ├── 内存充裕 → HNSW
│ ├── 需高压缩 → IVF_PQ
│ └── 不想调参 → AUTOINDEX
├── > 1亿, 内存有限 → DiskANN
└── 有 GPU → GPU_CAGRA / GPU_IVF_FLAT
稀疏向量 → SPARSE_INVERTED_INDEX
全文搜索(BM25) → Tantivy INVERTED 索引
去重/指纹 → MINHASH_LSH
性能调优要点
- 索引参数:
nlist(聚类数,约为 4×sqrt(数据量))、M(HNSW 连接数,越大越精确但越占内存)、nprobe(搜索时探测的聚类数,越大召回率越高但越慢) - 一致性级别:
Strong(强一致)↔Eventually(最终一致,最低延迟)↔Bounded(有界staleness)↔Session(会话内一致) - 副本: 读多写少时增加 QueryNode 副本数可提升吞吐
- 分区: 按时间/业务维度分区可缩小搜索范围,显著加速过滤查询
下一步
- Milvus 官方文档 — 各特性的完整说明
- 教程大全 — 动手实践各种场景
- 向量数据库基准测试 — 生产级性能评估
- Discord 社区 / Slack — 提问和交流
- GitHub Issues — 报告 Bug、提需求
- Twitter/X @milvusio — 最新动态