Article

向量数据库Milvus

更新于:2026-07-16

第一章:Milvus 概述与核心概念

1.1 什么是 Milvus?

概念名称说明注意事项
Milvus一个开源的向量数据库,专为高效存储、索引和搜索大规模向量数据而设计,支持 AI 应用中的相似性检索场景。Milvus 本身不处理原始数据(如图像、文本),需由上游模型(如 BERT、ResNet)生成向量后存入。
开源性质由 Zilliz 发起,现为 LF AI & Data 基金会孵化项目,采用 Apache 2.0 许可证。社区版免费使用;企业版提供额外功能(如 RBAC、审计日志)。
核心目标解决高维向量的”近似最近邻”(ANN)搜索问题,在海量数据下实现低延迟、高吞吐的相似性查询。不适用于精确匹配或事务型操作(如 ACID)。

1.2 向量数据库的基本原理

概念名称说明注意事项
向量化(Embedding)将非结构化数据(文本、图像等)通过机器学习模型转换为固定长度的数值向量,保留语义信息。向量质量直接影响检索效果;需选择合适的预训练模型。
相似性度量衡量两个向量之间”距离”或”相似度”的数学方法,常见包括:欧氏距离(L2)、内积(IP)、余弦相似度(Cosine)。Milvus 中 metric_type 需与向量归一化方式匹配(如 Cosine 等价于归一化后的 IP)。
近似最近邻(ANN)在牺牲少量精度的前提下,大幅加速高维空间中最近邻搜索的技术,避免全量暴力计算(Brute-force)。ANN 索引需权衡召回率(Recall)、延迟与内存占用。
向量索引对向量数据构建的数据结构(如 IVF、HNSW),用于加速 ANN 搜索。索引构建是异步过程,插入数据后需调用 create_index 触发。

1.3 Milvus 的架构组成

概念名称说明注意事项
Proxy接收客户端请求的入口节点,负责请求解析、校验、分发和结果聚合。所有 SDK 请求均通过 Proxy 路由,支持负载均衡。
Root Coordinator (RootCoord)全局元数据管理与 DDL(如创建集合)协调器。单点主控,集群模式下需高可用部署。
Data Coordinator (DataCoord)管理数据节点(DataNode)与日志快照(Binlog),协调数据持久化。负责触发 flush 和 compaction 操作。
Query Coordinator (QueryCoord)调度查询任务,管理查询节点(QueryNode)的加载与搜索。控制 segment 加载到内存供搜索使用。
Index Coordinator (IndexCoord)调度索引构建任务,管理 IndexNode。索引构建为资源密集型操作,建议独立节点运行。
存储层(MinIO / S3 + ETCD + Pulsar / Kafka)分别用于对象存储(向量/标量数据)、元数据存储(ETCD)、消息队列(日志流)。生产环境必须使用持久化存储,避免数据丢失。
SDK(Python/Java/Go/Node.js)客户端开发工具包,封装 gRPC 调用,提供高层 API。推荐使用 pymilvus(Python SDK),文档最完善。

1.4 Milvus 与其他向量数据库的对比

框架名称所属类别用途适用场景注意事项
Milvus开源向量数据库大规模 ANN 搜索、AI 应用集成推荐系统、RAG、图像检索、需要水平扩展的生产环境架构较复杂,适合中大型团队;社区活跃
Pinecone托管向量数据库(SaaS)快速构建向量搜索应用初创公司、MVP 验证、无运维能力团队闭源,按用量计费,数据出域风险需评估
Weaviate向量搜索引擎(含图谱)语义搜索 + 知识图谱需要结合本体(schema)与向量的混合场景内置向量化模块(可选),但性能弱于专用 ANN 引擎
QdrantRust 编写的向量数据库高性能 ANN 搜索低延迟要求、边缘部署、Rust 技术栈团队支持 payload 过滤,但集群功能较新,稳定性待验证
FAISS(Facebook)向量索引库(非数据库)单机向量索引与搜索研究实验、离线批处理、无需持久化场景无服务管理、无并发控制、无标量过滤,不适合在线服务

第二章:环境搭建与快速入门

2.1 安装 Milvus(单机版 / 集群版)

步骤名称操作细节注意事项
安装 Docker 和 Docker Compose执行官方命令安装 Docker 引擎及 docker-compose 工具(Linux/macOS/Windows WSL2)。Windows 用户建议使用 WSL2,避免 Docker Desktop 性能问题。
下载 Milvus 单机版配置文件运行 wget https://github.com/milvus-io/milvus/releases/download/v2.4.0/milvus-standalone-docker-compose.yml -O docker-compose.yml版本号(如 v2.4.0)需替换为最新稳定版。
启动单机版 Milvus在配置文件目录执行 docker-compose up -d首次启动需拉取多个镜像(约 2–5 GB),确保网络畅通。
安装集群版(Kubernetes)使用 Helm Chart:helm repo add milvus https://milvus-io.github.io/milvus-helm/,然后 helm install my-release milvus/milvus需提前部署 Kubernetes 集群(如 Minikube、EKS、ACK),并配置持久化存储。
验证组件状态单机版:docker-compose ps;集群版:kubectl get pods -l app.kubernetes.io/instance=my-release所有组件状态应为 Up(单机)或 Running(集群),若失败需检查日志。

2.2 启动与验证服务

步骤名称操作细节注意事项
检查服务端口默认 Proxy 端口为 19530(gRPC),RESTful API 端口为 9091(需启用)。若修改了 docker-compose.yml 中的端口映射,需对应调整客户端连接地址。
使用 milvus-cli 验证安装 CLI:pip install milvus-cli,然后运行 milvus_cli,执行 connect --host localhost --port 19530CLI 适合交互式调试,但不适用于程序化集成。
查看健康状态通过 REST API(若启用):curl http://localhost:9091/healthz 应返回 {"status":"ok"}REST 接口默认未开启,需在配置文件中设置 rest.enable: true
检查依赖服务确认 etcd、minio、pulsar/kafka 容器正常运行(单机版)或 Pod 就绪(集群版)。任一依赖服务异常将导致 Milvus 不可用。

2.3 使用 Python SDK 连接 Milvus

方法名称语法用途代码示例注意事项
connections.connectconnections.connect(alias="default", host="localhost", port=19530)建立与 Milvus 服务的连接from pymilvus import connections
connections.connect("default", host="localhost", port=19530)
alias 用于多连接管理;默认使用 “default”;host 可为 IP 或域名
connections.list_connectionsconnections.list_connections()列出当前所有已建立的连接print(connections.list_connections())返回元组列表
connections.get_connectionconnections.get_connection(alias="default")获取指定别名的连接对象client = connections.get_connection("default")若连接未建立,返回 None
connections.disconnectconnections.disconnect(alias="default")断开指定连接connections.disconnect("default")程序退出前建议显式断开,释放资源

2.4 Hello Milvus:第一个向量插入与查询示例

方法名称语法用途代码示例注意事项
CollectionCollection(name, schema=None, using="default", shards_num=2)创建或获取集合实例from pymilvus import Collection, FieldSchema, CollectionSchema, DataType
fields = [
FieldSchema("id", DataType.INT64, is_primary=True, auto_id=True),
FieldSchema("embedding", DataType.FLOAT_VECTOR, dim=128)
]
schema = CollectionSchema(fields, "hello milvus")
collection = Collection("hello_milvus", schema)
首次创建需定义 schema;后续可直接通过名称获取已有集合
insertcollection.insert(data)向集合插入向量数据import random
vectors = [[random.random() for _ in range(128)] for _ in range(10)]
collection.insert([vectors])
data 为列表的列表,顺序需与 schema 字段一致;标量字段可省略(若 auto_id=True)
create_indexcollection.create_index(field_name, index_params)为向量字段构建索引index_params = {"index_type": "IVF_FLAT", "metric_type": "L2", "params": {"nlist": 128}}
collection.create_index("embedding", index_params)
必须在搜索前调用;否则会触发 FLAT 暴力搜索(性能差)
loadcollection.load()将集合数据加载到内存供查询collection.load()插入后必须 load 才能搜索;首次 load 可能较慢
searchcollection.search(data, anns_field, param, limit)执行向量相似性搜索search_vectors = [[random.random() for _ in range(128)]]
search_params = {"metric_type": "L2", "params": {"nprobe": 10}}
results = collection.search(search_vectors, "embedding", search_params, limit=5)
data 为查询向量列表;anns_field 指定向量字段;limit 控制返回 top-k 结果
drop_collectionutility.drop_collection(name)删除集合(含数据和索引)from pymilvus import utility
utility.drop_collection("hello_milvus")
操作不可逆,谨慎使用

第三章:数据模型与集合管理

3.1 Collection(集合)的概念与创建

概念/方法名称说明 / 语法用途代码示例注意事项
CollectionMilvus 中存储向量和标量数据的基本单元,类似关系数据库中的”表”。组织和管理结构化向量数据一个 Milvus 实例可包含多个 Collection,彼此隔离
创建 CollectionCollection(name, schema, using="default", shards_num=2, ...)显式定义并创建新集合from pymilvus import Collection, CollectionSchema
collection = Collection("my_collection", schema)
集合名需全局唯一;若已存在同名集合且 schema 不同,将报错
获取已有 CollectionCollection(name)获取已存在的集合实例(无需重复传 schema)collection = Collection("my_collection")若集合不存在,会抛出异常
has_collectionutility.has_collection(collection_name, using="default")检查集合是否存在from pymilvus import utility
exists = utility.has_collection("my_collection")
返回布尔值,用于安全判断
drop_collectionutility.drop_collection(collection_name, using="default")删除集合及其所有数据和索引utility.drop_collection("my_collection")不可逆操作,删除后无法恢复
shards_num创建时指定分片数量(默认为 2)控制数据写入并行度,影响吞吐Collection("my_col", schema, shards_num=4)分片数一旦设定不可修改;建议根据写入负载调整

3.2 Schema(模式)定义与字段类型

字段属性 / 方法语法 / 说明用途代码示例注意事项
FieldSchemaFieldSchema(name, dtype, description="", is_primary=False, auto_id=False, dim=None, max_length=None, ...)定义集合中单个字段的元信息FieldSchema("id", DataType.INT64, is_primary=True, auto_id=True)必须指定 dtype;主键字段必须为 INT64 或 VARCHAR
CollectionSchemaCollectionSchema(fields, description="", enable_dynamic_field=False)聚合多个字段,构成完整集合结构CollectionSchema([id_field, vec_field], "user embeddings")fields 列表顺序无强制要求,但需包含一个主键
DataType.INT64整型标量字段存储用户 ID、时间戳等FieldSchema("user_id", DataType.INT64)可作为主键(is_primary=True)
DataType.VARCHAR可变长字符串存储文本标签、名称等FieldSchema("name", DataType.VARCHAR, max_length=64)必须指定 max_length(1–65535)
DataType.FLOAT_VECTOR浮点向量字段存储嵌入向量(如 BERT 输出)FieldSchema("emb", DataType.FLOAT_VECTOR, dim=768)必须指定 dim(正整数),所有向量维度必须一致
DataType.BINARY_VECTOR二值向量字段存储哈希编码等二进制向量FieldSchema("hash", DataType.BINARY_VECTOR, dim=256)dim 表示比特数,实际字节数为 dim/8
is_primary字段参数,标记为主键唯一标识实体FieldSchema("id", DataType.VARCHAR, is_primary=True, max_length=32)仅支持一个主键字段;VARCHAR 主键不支持 auto_id
auto_id自动递增主键(仅 INT64)自动生成唯一 IDFieldSchema("id", DataType.INT64, is_primary=True, auto_id=True)若设为 True,插入时不能提供该字段值
enable_dynamic_fieldCollectionSchema 参数允许插入未在 schema 中声明的字段(类似 JSON 扩展)CollectionSchema([...], enable_dynamic_field=True)Milvus 2.4+ 支持;动态字段仅支持标量类型

3.3 索引类型与参数配置

索引类型适用场景参数说明代码示例注意事项
FLAT小数据集(< 10K 向量)或需要 100% 精确结果无额外参数{"index_type": "FLAT", "metric_type": "L2"}不建索引也可搜索(默认回退到 FLAT),但性能差
IVF_FLAT中等规模数据,平衡速度与精度nlist(聚类中心数){"index_type": "IVF_FLAT", "metric_type": "L2", "params": {"nlist": 100}}nlist 建议为 sqrt(N),N 为向量总数
IVF_SQ8内存受限场景,量化压缩向量nlist{"index_type": "IVF_SQ8", "metric_type": "L2", "params": {"nlist": 100}}向量被量化为 1 字节/维度,精度略有损失
HNSW低延迟、高召回场景(推荐)M(每节点连接数),efConstruction(建图时候选数){"index_type": "HNSW", "metric_type": "IP", "params": {"M": 16, "efConstruction": 100}}内存占用较高;M 越大精度越高但内存越大
ANNOY轻量级、可持久化索引n_trees(树数量){"index_type": "ANNOY", "metric_type": "L2", "params": {"n_trees": 50}}构建快,适合静态数据集
DISKANN超大规模(十亿级)、磁盘索引search_cache_budget_gb, build_dram_budget_gb{"index_type": "DISKANN", "metric_type": "L2", "params": {"search_cache_budget_gb": 10}}仅企业版支持;需 SSD 存储
metric_type距离度量方式L2(欧氏距离)、IP(内积)、COSINE(余弦)必须与向量生成方式匹配使用 COSINE 时,向量应预先 L2 归一化;否则等效于 IP

3.4 Partition(分区)与 Alias(别名)管理

方法名称语法用途代码示例注意事项
create_partitioncollection.create_partition(partition_name)在集合内创建逻辑分区collection.create_partition("part_2024")分区名在同一集合内唯一;可用于按时间/业务分片
has_partitioncollection.has_partition(partition_name)检查分区是否存在if collection.has_partition("part_2024"): ...返回布尔值
drop_partitioncollection.drop_partition(partition_name)删除指定分区及其数据collection.drop_partition("old_part")不可逆操作
insert into partitioncollection.insert(data, partition_name=...)向指定分区插入数据collection.insert([ids, vectors], partition_name="part_2024")若未指定,默认插入 _default 分区
search with partitioncollection.search(..., partition_names=[...])限定搜索范围到特定分区collection.search(vectors, "embedding", params, limit=5, partition_names=["part_2024"])可提升查询效率,减少扫描数据量
create_aliasutility.create_alias(collection_name, alias, using="default")为集合创建别名utility.create_alias("my_collection_v2", "user_emb")便于版本切换或蓝绿部署
drop_aliasutility.drop_alias(alias, using="default")删除别名utility.drop_alias("user_emb")不影响原集合
alter_aliasutility.alter_alias(collection_name, alias, using="default")将别名指向另一个集合utility.alter_alias("my_collection_v3", "user_emb")实现零停机切换;原集合不再被别名引用

第四章:向量操作与检索

4.1 插入向量数据

方法名称语法用途代码示例注意事项
Collection.insertcollection.insert(data, partition_name=None, timeout=None)向集合(或指定分区)插入结构化数据import random
vectors = [[random.random() for _ in range(128)] for _ in range(5)]
ids = [1, 2, 3, 4, 5]
collection.insert([ids, vectors])
data 必须是列表的列表,顺序与 schema 字段一致;若主键 auto_id=True,则无需提供 ID
批量插入建议单次插入 1K–10K 条提高写入吞吐,减少 gRPC 开销collection.insert([large_id_list, large_vector_list])避免单次插入过大(>100K),可能触发 gRPC 消息大小限制(默认 100MB)
动态字段插入当 enable_dynamic_field=True 时,可传入字典插入 schema 未定义的标量字段collection.insert([ids, vectors, {"tag": ["A", "B", ...]}])动态字段仅支持标量类型(INT64、VARCHAR 等),不支持向量

4.2 查询与删除实体

方法名称语法用途代码示例注意事项
Collection.querycollection.query(expr, output_fields=None, partition_names=None, timeout=None)基于主键或标量条件查询实体results = collection.query(expr="id in [1, 2, 3]", output_fields=["id", "embedding"])expr 使用类似 SQL 的布尔表达式;必须包含主键或已建标量索引的字段
Collection.deletecollection.delete(expr, partition_names=None, timeout=None)删除满足条件的实体collection.delete(expr="id in [1, 2]")删除操作异步生效;数据在 compaction 后才真正释放空间
标量过滤字段要求字段需为标量类型(非向量)支持等值、范围、IN 等操作expr="age > 25 and city == 'Beijing'"若字段未建标量索引,全表扫描性能差;建议对高频过滤字段建索引
flushutility.flush([collection_name], using="default")强制将缓冲区数据持久化到存储utility.flush(["my_collection"])默认每秒自动 flush;手动 flush 可确保刚插入数据可被 query 查到

4.3 向量相似性搜索(Search)

方法名称语法用途代码示例注意事项
Collection.searchcollection.search(data, anns_field, param, limit, expr=None, output_fields=None, partition_names=None, timeout=None)执行 ANN 向量相似性搜索search_vec = [[0.1, 0.2, ..., 0.128]]
res = collection.search(search_vec, "embedding", {"metric_type": "L2", "params": {"nprobe": 10}}, limit=3)
data 为二维列表([[vec1], [vec2], ...]);anns_field 必须是向量字段名
返回结果结构每个查询返回一个 Hit 对象列表包含 id、distance、entity(若 output_fields 指定)for hit in res[0]: print(hit.id, hit.distance)distance 值含义取决于 metric_type(L2 越小越相似,IP 越大越相似)
必须 load搜索前需调用 collection.load()将 segment 加载到 QueryNode 内存collection.load()未 load 会报错:“collection not loaded”
多向量搜索一次传入多个查询向量批量处理查询请求collection.search([vec1, vec2, vec3], ...)每个向量独立搜索,结果按输入顺序返回

4.4 混合查询(Scalar + Vector)

方法名称语法用途代码示例注意事项
Collection.search with expr在 search 中使用 expr 参数先按标量条件过滤,再在子集中做向量搜索collection.search(vectors, "embedding", params, limit=5, expr="category == 'electronics'")expr 过滤发生在向量搜索之前,显著缩小搜索范围
支持的标量操作符==, !=, >, <, >=, <=, in, not in构建布尔过滤条件expr="price >= 100 and price <= 500"不支持 LIKE、正则等复杂文本操作;不支持 between,需改写为范围表达式
标量字段索引对高频过滤字段创建标量索引加速 expr 过滤collection.create_index("category", {"index_type": "Trie"})VARCHAR 推荐 Trie 索引,INT64 可用 Sorted 或 Inverted
性能影响混合查询性能 ≈ 标量过滤速度 + 向量搜索速度过滤后数据量越小,向量搜索越快若 expr 过滤后无数据,返回空结果,不报错

4.5 搜索参数详解(top_k, metric_type, params 等)

参数名称说明取值示例用途注意事项
limit (top_k)返回最相似的前 k 个结果limit=10控制返回数量受服务端 max_top_k 限制(默认 16384)
metric_type相似性度量方式"L2", "IP", "COSINE"定义距离计算方法必须与建索引时的 metric_type 一致;COSINE 要求向量已 L2 归一化
params.nprobe (IVF)搜索时探测的聚类中心数{"nprobe": 10}平衡精度与速度(越大越准越慢)建议 nprobe ≈ sqrt(nlist);最大不超过 nlist
params.ef (HNSW)搜索时的候选队列大小{"ef": 100}控制 HNSW 搜索深度ef ≥ limit;越大召回率越高,延迟越高
params.search_length (ANNOY)遍历的树节点数{"search_k": -1}ANNOY 中 search_k = search_length * n_treessearch_k=-1 表示自动设为 n_trees * limit
round_decimal距离值保留小数位数round_decimal=3控制返回 distance 精度仅影响显示,不影响排序
ignore_growing是否忽略正在插入的增量数据ignore_growing=True避免读到未完成写入的数据默认 False;高一致性场景可设为 True

第五章:索引与性能优化

5.1 支持的索引类型(FLAT, IVF_FLAT, HNSW, ANNOY 等)

索引类型向量类型支持精度内存占用构建速度搜索速度适用场景注意事项
FLATFLOAT_VECTOR, BINARY_VECTOR100%(精确)高(原始向量)快(无构建)慢(O(N))小数据集(<10K)、测试验证无需显式建索引;搜索时自动使用
IVF_FLATFLOAT_VECTOR高(可调)高(原始向量 + 聚类中心)快(O(sqrt(N)))中等规模(10K–10M)需设置 nlist;nprobe 控制精度/速度
IVF_SQ8FLOAT_VECTOR中(量化损失)低(1字节/维度)内存受限、大规模部署不支持 BINARY_VECTOR;精度略低于 IVF_FLAT
IVF_PQFLOAT_VECTOR中低(乘积量化)极低(可配置压缩比)超大规模、内存极度受限需调参 m(子空间数),m 必须整除 dim
HNSWFLOAT_VECTOR高(图结构)极快(O(log N))低延迟、高召回生产场景M 和 efConstruction 影响内存与精度;不支持动态插入后高效更新
ANNOYFLOAT_VECTOR中高中(树结构)静态数据集、轻量部署构建后不可增量更新;适合只读场景
DISKANNFLOAT_VECTOR低(主存缓存+磁盘)快(SSD 加速)十亿级向量、成本敏感仅 Milvus 企业版支持;需 NVMe SSD
BIN_FLATBINARY_VECTOR100%中(原始比特)小规模二值向量metric_type 仅支持 JACCARD、HAMMING、TANIMOTO
BIN_IVF_FLATBINARY_VECTOR中等规模二值向量nlist 参数同样适用

5.2 索引构建与管理

方法名称语法用途代码示例注意事项
Collection.create_indexcollection.create_index(field_name, index_params, index_name=None, timeout=None)为指定字段创建索引index_params = {"index_type": "HNSW", "metric_type": "IP", "params": {"M": 16, "efConstruction": 100}}
collection.create_index("embedding", index_params)
同一字段只能有一个索引;重复调用会覆盖(异步生效)
Collection.has_indexcollection.has_index(index_name=None)检查是否已为向量字段建索引if not collection.has_index(): print("No index")若未指定 index_name,检查默认向量字段索引
Collection.indexcollection.index获取当前索引对象idx = collection.index
print(idx.params)
返回 Index 对象,包含 params、field_name 等属性
Collection.drop_indexcollection.drop_index(index_name=None)删除现有索引collection.drop_index()删除后搜索将回退到 FLAT(暴力搜索)
异步构建create_index 为异步操作不阻塞主线程collection.create_index(...)
print("Indexing started")
可通过 IndexCoord 日志或监控观察进度
多字段索引分别对不同向量字段建索引支持多向量集合collection.create_index("vec1", params1)
collection.create_index("vec2", params2)
每个向量字段独立索引;搜索时指定 anns_field

5.3 搜索性能调优策略

调优方向策略说明注意事项
索引选型根据数据规模选择:小数据用 FLAT,中等用 IVF_FLAT/HNSW,超大用 DISKANN/PQ平衡精度、延迟、内存HNSW 适合低延迟;IVF 系列适合高吞吐
nlist / nprobe(IVF)nlist ≈ sqrt(N),nprobe ≈ sqrt(nlist)提高召回率同时控制延迟nprobe 越大越准但越慢;线上建议固定 nprobe
HNSW 参数M=8~64,efConstruction=100~500,ef≥limitM 控制图密度,ef 控制搜索深度M 越大内存越高;efConstruction 过大会导致构建慢
分区过滤使用 partition_names 限定搜索范围减少扫描数据量适用于时间分区、业务隔离场景
标量索引对高频过滤字段(如 category、status)建标量索引加速 expr 过滤阶段VARCHAR 用 Trie,INT64 用 Sorted 或 Inverted
load 前预热在低峰期执行 load避免首次搜索冷启动延迟可结合 Kubernetes readiness probe
批量搜索一次 search 传入多个查询向量提高 QPS,降低网络开销单次 batch size 建议 10–100
避免频繁建索引数据写入完成后统一建索引减少 I/O 和 CPU 开销流式写入场景可定期重建索引

5.4 资源配置与硬件建议

组件最小配置(单机开发)推荐生产配置(10M 向量)说明注意事项
Proxy2 vCPU, 4 GB RAM4–8 vCPU, 8–16 GB RAM处理客户端请求高并发时需水平扩展多个 Proxy
QueryNode4 vCPU, 8 GB RAM16–32 vCPU, 64–128 GB RAM加载 segment 并执行搜索内存必须 ≥ 向量数据 + 索引大小;HNSW 内存需求高
DataNode2 vCPU, 4 GB RAM8 vCPU, 32 GB RAM处理数据 flush 和 compaction写入吞吐高时需更多资源
IndexNode4 vCPU, 8 GB RAM16 vCPU, 64 GB RAM异步构建索引索引构建为 CPU/内存密集型,建议独占节点
MinIO/S3本地磁盘 50 GB云存储(≥1 TB,高吞吐)存储原始向量和标量建议使用 SSD;IOPS 影响 flush 性能
ETCD2 vCPU, 4 GB RAM4 vCPU, 8 GB RAM(集群模式)存储元数据必须持久化;避免单点故障
Pulsar/Kafka2 vCPU, 4 GB RAM8+ vCPU, 32+ GB RAM消息队列,解耦写入Pulsar 更适合 Milvus;需配置足够 ledger 空间
网络1 Gbps10 Gbps节点间通信QueryNode 与 MinIO 之间带宽影响 load 速度
向量规模估算10M × 768 维 FLOAT ≈ 30 GB 原始数据内存需求 ≈ 原始数据 × 1.5(含索引)HNSW 索引可能达原始数据 2–3 倍内存

第六章:高级功能

6.1 动态 Schema 与多向量支持

功能名称说明语法 / 操作代码示例注意事项
动态 Schema(Dynamic Schema)允许插入未在 CollectionSchema 中显式声明的标量字段,类似 JSON 扩展创建集合时设置 enable_dynamic_field=Truefrom pymilvus import CollectionSchema, FieldSchema, DataType
schema = CollectionSchema([
FieldSchema("id", DataType.INT64, is_primary=True),
FieldSchema("vec", DataType.FLOAT_VECTOR, dim=128)
], enable_dynamic_field=True)
col = Collection("dyn_col", schema)
仅 Milvus 2.4+ 支持;动态字段必须为标量类型(不支持向量)
插入动态字段在 insert 时传入字典作为额外字段collection.insert([ids, vectors, {"tag": [...], "score": [...]}])col.insert([[1], [[0.1]*128], {"category": ["tech"], "price": [299]}])字段名不能与 schema 中已定义字段冲突
多向量字段一个集合包含多个向量字段(如文本向量 + 图像向量)在 schema 中定义多个 FLOAT_VECTOR / BINARY_VECTOR 字段fields = [
FieldSchema("id", DataType.INT64, is_primary=True),
FieldSchema("text_emb", DataType.FLOAT_VECTOR, dim=768),
FieldSchema("img_emb", DataType.FLOAT_VECTOR, dim=512)
]
schema = CollectionSchema(fields)
每个向量字段可独立建索引、独立搜索
多向量搜索指定 anns_field 进行不同向量的搜索collection.search(..., anns_field="text_emb", ...)res1 = col.search([query_text_vec], "text_emb", params, limit=5)
res2 = col.search([query_img_vec], "img_emb", params, limit=5)
一次 search 只能指定一个 anns_field;如需融合,需客户端后处理

6.2 Time Travel 与数据版本控制

概念/方法名称说明语法 / 操作代码示例注意事项
Time TravelMilvus 自动保留最近一段时间(默认 1 小时)的数据快照,支持按时间点查询或恢复通过 guarantee_timestamp 或 travel_timestamp 参数实现from pymilvus import utility
ts = utility.mkts_from_hybridts(utility.current_time(), milliseconds=30*60*1000) # 30分钟前
results = collection.query(expr="id > 0", travel_timestamp=ts)
依赖 Pulsar/Kafka 的消息保留策略;若消息被清理,则无法回溯
获取当前时间戳utility.current_time()获取当前 Hybrid Timestampcurrent_ts = utility.current_time()返回 hybrid timestamp(64位整数),非 Unix 时间
转换时间戳utility.mkts_from_unixtime(unix_time, milliseconds=0)
utility.mkts_from_hybridts(hybrid_ts, milliseconds=delta)
将 Unix 时间或相对时间转换为 Milvus 时间戳ts_1h_ago = utility.mkts_from_hybridts(utility.current_time(), milliseconds=-3600000)milliseconds 为负表示过去时间
查询历史数据在 query 或 search 中使用 travel_timestampcollection.search(..., travel_timestamp=ts_1h_ago)仅能回溯 retention window 内的数据(由配置 msg_retention_time_minutes 控制,默认 60 分钟)
数据不可变性插入/删除操作不会覆盖原数据,而是追加日志Time Travel 基于日志重放实现,非传统数据库的 MVCC

6.3 RBAC 权限控制(企业版)

功能名称说明操作方式示例 / 说明注意事项
角色(Role)预定义或自定义权限集合,如 admin、reader、writer通过 Milvus Enterprise REST API 或 CLI 管理CREATE ROLE analyst;仅企业版支持;社区版无此功能
用户(User)绑定角色,用于身份认证CREATE USER alice IDENTIFIED BY 'password';
GRANT ROLE analyst TO alice;
支持 LDAP 集成(企业版高级特性)
权限粒度支持集合级(Collection)、全局级(Global)权限GRANT SELECT ON COLLECTION my_col TO analyst;权限类型:SELECT(查询)、INSERT、DELETE、CREATE_INDEX、ALL不支持字段级(列级)权限控制
启用认证在 milvus.yaml 中设置 milvus.authn.enabled: true配置后所有 SDK 连接需提供用户名密码connections.connect(user="alice", password="xxx", ...)若未启用 authn,RBAC 无效
审计日志记录用户操作(企业版)日志输出到指定文件或 Kafka需额外配置审计日志路径和格式

⚠️ 注意:RBAC 为 Milvus 企业版专属功能,社区版(开源版)不支持。开发测试请使用企业版试用镜像或联系 Zilliz。

6.4 备份与恢复机制

方法/工具名称说明操作步骤代码 / 命令示例注意事项
Milvus Backup(开源工具)社区维护的备份工具,基于 MinIO 快照和元数据导出1. 安装 milvus-backup
2. 配置源和目标 MinIO
3. 执行备份/恢复
milvus-backup backup --backup_name=my_backup
milvus-backup restore --backup_name=my_backup
GitHub 项目:milvus-io/milvus-backup;需停写或容忍备份期间数据不一致
企业版备份(Zilliz Cloud / Enterprise)支持在线一致性快照、增量备份通过管理控制台或 API 触发提供 SLA 保障;支持 PITR(Point-in-Time Recovery)
手动备份(不推荐)直接复制 MinIO 数据 + ETCD 快照1. 停止 Milvus
2. 备份 MinIO bucket
3. 导出 ETCD 数据
etcdctl snapshot save snap.db极易出错;恢复时版本必须完全一致;仅用于紧急恢复
恢复流程1. 清空目标集群存储
2. 恢复 MinIO 数据
3. 恢复 ETCD(若需要)
4. 启动 Milvus
恢复后需重新 load 集合才能搜索
限制不支持跨版本恢复备份与恢复必须使用相同 Milvus 主版本(如 2.4.x → 2.4.y)

💡 建议:生产环境优先使用 milvus-backup 工具或企业版备份方案,避免手动操作。

第七章:生产部署与运维

7.1 Milvus 集群部署(基于 Kubernetes)

步骤名称操作细节命令 / 配置示例注意事项
准备 Kubernetes 集群使用 EKS、ACK、GKE 或自建 K8s(≥v1.20)kubectl version确保集群有足够资源(CPU ≥ 16 核,内存 ≥ 64 GB)
安装 HelmHelm 是 Milvus 官方推荐的部署工具curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bashHelm v3+,无需 Tiller
添加 Milvus Helm 仓库获取官方 Charthelm repo add milvus https://milvus-io.github.io/milvus-helm/
helm repo update
确保网络可访问 GitHub Pages
创建 values.yaml 配置文件自定义存储、副本数、资源限制等yaml\nminio:\n enabled: true\netcd:\n replicaCount: 3\nkafka:\n enabled: false\npulsar:\n enabled: true\ncomponents:\n proxy:\n replicas: 2\n queryNode:\n replicas: 3\n resources:\n limits:\n memory: "32Gi"\n生产环境必须启用持久化存储(MinIO/S3 + ETCD + Pulsar);禁用 standalone 模式
部署 Milvus使用 Helm 安装helm install my-milvus milvus/milvus -f values.yaml --namespace milvus --create-namespace首次部署需 5–10 分钟拉取镜像
验证部署状态检查所有 Pod 是否 Runningkubectl get pods -n milvus所有组件应为 Running 状态;若 CrashLoopBackOff,检查日志
暴露服务(可选)通过 LoadBalancer 或 Ingress 暴露 Proxykubectl expose deployment my-milvus-milvus-proxy --port=19530 --type=LoadBalancer -n milvus默认 ClusterIP 仅集群内访问;外部访问需显式暴露

7.2 监控与日志(Prometheus + Grafana)

组件配置方式关键指标注意事项
PrometheusMilvus 内置 metrics 接口(/metrics),默认端口 9091query_node_search_latency
insert_row_count
index_request_success
values.yaml 中启用:
metrics:
enabled: true
serviceMonitor:
enabled: true
ServiceMonitor(Prometheus Operator)自动发现 Milvus Pod 并抓取指标需已部署 Prometheus Operator
Grafana Dashboard导入官方 JSON 模板(ID: 13749)可视化 QPS、延迟、资源使用率下载地址:https://grafana.com/grafana/dashboards/13749
日志收集使用 Filebeat / Fluentd / Loki 收集容器日志错误日志关键词:ERROR, panic, timeout日志级别可通过 log.level 配置(debug/info/warn/error)
告警规则(Alertmanager)配置关键告警(如 QueryNode OOM、Pulsar backlog 积压)示例规则:rate(milvus_query_node_search_latency_seconds_sum[5m]) > 1.0建议监控:
- 组件存活
- 搜索延迟 > 1s
- 插入队列积压
启用 RESTful 监控接口在 Proxy 配置中开启yaml\nproxy:\n restful:\n enabled: true\n port: 9091\n/healthz/metrics 依赖此配置

7.3 扩容与高可用方案

扩容目标操作方式命令 / 配置注意事项
扩容 Proxy增加入口节点,提升连接处理能力修改 values.yaml
yaml\ncomponents:\n proxy:\n replicas: 3\n
然后 helm upgrade my-milvus milvus/milvus -f values.yaml -n milvus
所有 Proxy 共享元数据,无状态,可任意扩缩
扩容 QueryNode提升搜索吞吐与并发能力增加 replicas 并分配足够内存新 QueryNode 自动从 MinIO 加载 segment;需确保内存 ≥ 数据集大小
扩容 DataNode提升写入吞吐增加 DataNode 副本数写入吞吐 ≈ DataNode 数量 × 单节点能力
扩容 IndexNode加速索引构建增加 IndexNode 副本索引任务自动分发到空闲 IndexNode
高可用保障ETCD 集群(3 节点)
Pulsar BookKeeper 多副本
MinIO 分布式模式(4 节点起)
Helm Chart 默认启用多副本单点组件(如 RootCoord)通过 K8s Deployment 自愈
负载均衡在 Proxy 前部署 HAProxy / Nginx / 云 SLB配置 TCP 透传 19530 端口gRPC 不支持 HTTP 层负载均衡,需 L4 转发
故障转移K8s 自动重启失败 Pod;Pulsar/ETCD 自动选举确保 PodDisruptionBudget 配置合理,避免批量驱逐

7.4 常见问题排查指南

问题现象可能原因排查步骤解决方案
连接被拒绝(Connection refused)Proxy 未运行或端口未暴露1. kubectl get pods -n milvus
2. kubectl get svc -n milvus
检查 Proxy Pod 状态;若为 ClusterIP,需 port-forward 或暴露服务
搜索返回空结果1. 未 load 集合
2. 向量未插入
3. metric_type 不匹配
1. collection.num_entities
2. collection.load()
3. 检查建索引和搜索的 metric_type
插入后必须 load;确认向量维度与 schema 一致
插入速度慢1. DataNode 资源不足
2. Pulsar 磁盘 IO 慢
3. 单次 batch 太小
1. 查看 DataNode CPU/Mem
2. 检查 Pulsar ledger disk latency
3. 增大 batch size(1K–10K)
升级 DataNode;使用 SSD;批量插入
内存溢出(OOMKilled)QueryNode 内存不足kubectl describe pod -n milvus <querynode-pod>增加 QueryNode 内存 limit;减少单集合数据量;改用 IVF_SQ8 降低内存
索引构建卡住IndexNode 资源不足或参数不合理1. kubectl logs -n milvus <indexnode-pod>
2. 检查 IndexCoord 日志
增加 IndexNode 内存;避免 dim 过大时使用 HNSW(M 过高)
Time Travel 无法回溯Pulsar 消息已过期检查 msg_retention_time_minutes 配置(默认 60)增大 retention 时间;但会增加存储成本
权限错误(企业版)用户未授权或认证未启用1. 检查 milvus.yamlauthn.enabled
2. 确认用户角色权限
启用认证;为用户授予对应集合权限

第八章:应用场景与案例

8.1 图像/视频相似检索

步骤名称操作细节代码示例注意事项
特征提取使用 CNN(如 ResNet、ViT)将图像/视频帧转换为向量from torchvision.models import resnet50
model = resnet50(pretrained=True)
model.eval()
with torch.no_grad():
embedding = model(img_tensor).flatten().tolist()
向量维度通常为 512/2048;建议 L2 归一化后使用 IP 或 COSINE
构建集合 Schema定义 ID、图像路径、向量字段fields = [
FieldSchema("img_id", DataType.INT64, is_primary=True),
FieldSchema("img_path", DataType.VARCHAR, max_length=256),
FieldSchema("embedding", DataType.FLOAT_VECTOR, dim=2048)
]
schema = CollectionSchema(fields)
可添加标量字段(如类别、拍摄时间)用于混合查询
批量插入图像向量遍历图像库,提取并插入向量img_ids = list(range(len(embeddings)))
paths = [f"/imgs/{i}.jpg" for i in img_ids]
collection.insert([img_ids, paths, embeddings])
建议每批 5K–10K 条;避免内存溢出
构建索引选择 HNSW 或 IVF_FLATindex_params = {"index_type": "HNSW", "metric_type": "IP", "params": {"M": 16, "efConstruction": 100}}
collection.create_index("embedding", index_params)
若向量已归一化,IP 等价于余弦相似度
相似图检索对查询图提取向量并搜索query_vec = extract_feature(query_img)
results = collection.search([query_vec], "embedding", {"metric_type": "IP", "params": {"ef": 64}}, limit=10)
返回结果包含 img_id 和 img_path,可用于展示
视频帧处理对关键帧或均匀采样帧分别建库每帧视为独立图像,或对视频聚合(如平均池化)聚合向量可代表整个视频,但丢失时序信息

8.2 推荐系统中的向量召回

步骤名称操作细节代码示例注意事项
用户/物品向量化使用双塔模型(DSSM)、GraphSAGE 等生成 user/item 向量user_emb = user_model(user_features)
item_emb = item_model(item_features)
向量需在同一语义空间;训练时使用对比学习或协同过滤目标
分别建库创建 user_collection 和 item_collectionitem_fields = [
FieldSchema("item_id", DataType.INT64, is_primary=True),
FieldSchema("category", DataType.VARCHAR, max_length=64),
FieldSchema("emb", DataType.FLOAT_VECTOR, dim=128)
]
item_col = Collection("items", CollectionSchema(item_fields))
物品库通常静态更新;用户向量可实时生成或缓存
实时召回在线服务中,用用户向量搜索物品库user_vec = get_user_embedding(user_id)
recs = item_col.search([user_vec], "emb", {"metric_type": "IP", "params": {"nprobe": 20}}, limit=100)
搜索延迟需 < 50ms;建议使用 HNSW 或 IVF_SQ8
混合过滤结合业务规则(如地域、库存)expr = "category == 'electronics' and in_stock == true"
recs = item_col.search(..., expr=expr, ...)
标量字段需建索引(如 Trie for VARCHAR)
多路召回融合Milvus 仅负责向量召回,与其他路(如热门、协同过滤)在排序层融合Milvus 输出作为粗排候选集,送入精排模型
增量更新新商品上线时插入向量item_col.insert([[new_id], [new_cat], [new_emb]])插入后需触发索引重建(或使用流式索引策略)

8.3 大模型 RAG 架构集成

步骤名称操作细节代码示例注意事项
文本分块将文档切分为语义完整的小段(chunk)from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=50)
chunks = splitter.split_text(doc)
避免跨句子切分;保留元数据(如 source、page)
向量化使用 embedding 模型(如 bge-large、text-embedding-ada-002)from sentence_transformers import SentenceTransformer
model = SentenceTransformer('BAAI/bge-large-en')
embeddings = model.encode(chunks).tolist()
选择与任务匹配的 embedding 模型;bge 系列在中文场景表现优异
构建知识库存储 chunk + 向量 + 元数据fields = [
FieldSchema("id", DataType.INT64, is_primary=True, auto_id=True),
FieldSchema("content", DataType.VARCHAR, max_length=2048),
FieldSchema("source", DataType.VARCHAR, max_length=256),
FieldSchema("embedding", DataType.FLOAT_VECTOR, dim=1024)
]
kb_col = Collection("rag_kb", CollectionSchema(fields, enable_dynamic_field=True))
content 长度需 ≤ max_length;可启用 dynamic_field 存 page 等额外信息
查询重写(可选)将用户问题改写为检索友好形式使用 LLM 生成关键词或假设答案提升召回率,但增加延迟
向量检索用问题向量搜索 top-k 相关 chunksquery_emb = model.encode([question]).tolist()
results = kb_col.search(query_emb, "embedding", {"metric_type": "IP", "params": {"ef": 128}}, limit=5, output_fields=["content", "source"])
limit 通常设为 3–5;output_fields 返回原文用于 prompt
构造 Prompt将检索结果拼接进 LLM promptprompt = f"基于以下资料回答问题:\n{results[0].entity.content}\n\n问题:{question}"需控制总 token 数不超过 LLM 上限
动态更新知识库支持新增/删除文档kb_col.delete(expr="source == 'old_doc.pdf'")
kb_col.insert([...])
删除后需 flush 并等待 compaction 生效

8.4 语义搜索与问答系统

步骤名称操作细节代码示例注意事项
构建 QA 对库存储 (question, answer) 对及其向量fields = [
FieldSchema("id", DataType.INT64, is_primary=True),
FieldSchema("question", DataType.VARCHAR, max_length=512),
FieldSchema("answer", DataType.VARCHAR, max_length=2048),
FieldSchema("q_emb", DataType.FLOAT_VECTOR, dim=768)
]
qa_col = Collection("faq_db", CollectionSchema(fields))
question 用于检索,answer 用于返回
问题向量化对用户输入问题编码q_emb = encoder.encode([user_question]).tolist()使用与入库相同的 encoder 模型
语义匹配搜索检索最相似的历史问题hits = qa_col.search(q_emb, "q_emb", {"metric_type": "COSINE", "params": {"ef": 100}}, limit=1)COSINE 要求向量 L2 归一化;若未归一化,改用 IP
置信度过滤判断是否命中有效答案if hits[0][0].distance > 0.7: # cosine similarity
answer = hits[0][0].entity.answer
else:
answer = "未找到相关答案"
阈值需根据数据分布校准;避免低质量匹配
支持多轮上下文将对话历史拼接进当前问题full_query = f"{history} {current_question}"需控制长度;可使用 sliding window
标量增强添加领域标签、时效性字段expr = "domain == 'finance' and valid_until >= 20260203"
hits = qa_col.search(..., expr=expr, ...)
提高答案相关性;避免返回过期政策
性能优化预加载高频 QA 集合qa_col.load() at startup确保首次查询无冷启动延迟