Milvus 3.0.0 于 2026 年 7 月 29 日正式 GA(依据 GitHub 标签与 LF AI & Data 基金会的双重验证)。官方 release notes 中有一句关键表述常被忽视:
这句话并非自谦,而是将 3.0 定位于 Beta 阶段的收尾,而非新功能的简单堆叠。若将其视为 2.6 到 3.0 的常规升级,很容易错过本次更新的核心主线。
在深入源码(internal/core/src/storage/loon_ffi/、internal/storagev2/、pkg/streaming/walimpls/)及官方文档库(web-content/v3.0.x)后,我们对本次发布的核心判断是:底层引入了 Storage V3 / Loon 抽象层;上层则重构了 External Collection、Snapshots、Online Schema、TEXT 字段、Sparse Index 等关键能力,这些才是真正改变工作流的核心。在讨论新功能之前,必须先理清这一层替换,否则容易混淆“上线即用”与“代码已存在”的边界。
本文不打算逐条罗列 release notes 中的 20 多项功能,仅挑选几个能改变工作流的能力、它们的适用边界,以及上线前必须了解的几个门槛进行阐述。
1. 主线:从云原生迈向湖原生
Milvus 2.x 的核心卖点是云原生——存算分离:无状态组件、对象存储底层、支撑 500 节点扩展。但这一思路在 2.6 版本已触及瓶颈,新增数据需要复制一份到 Milvus。
3.0 不再专注于“扩展”问题,而是更换了抽象层。从 release notes 提到的“新一代存储抽象”、源码 internal/storagev2/ 目录以及 loon_ffi/ 路径下的 FFI 封装来看,Milvus 将存储底座替换为 Storage V3 / Loon:一种基于对象存储的 manifest 列存格式。
更准确地说,Loon 的核心作用是:将 segment 的元数据(manifest)与数据文件(column files)解耦,查询时按 manifest 精准获取列。官方博客给出了一组厂商口径数据(3M 行 / 128-dim / S3 / 256 并发读取):Parquet 基础读取每点约 9.4 MB,Vortex + Loon 降至约 0.07 MB,I/O 节省约 135 倍。
但需注意,这个数字仅来源于官方博客,尚未有第三方独立复现。在你的数据集上能否重现,取决于行数、向量维度、并发读取模式以及 manifest pruning 命中率。因此 Loon 的 135× 是参考值,并非承诺。
这一底层替换的收益,要到上层能力层面才能真正体现。
Milvus 2.x 云原生 与 3.0 lake-native 架构演进对比
2. 以下 4 项能力,真正改变工作流
3.0 的 release notes 列出了 20 多项能力,但大部分是功能补全或工具链优化。下面 4 项是直接改变你使用 Milvus 方式的能力,按影响从大到小排列。
2.1 Online schema 演进:加字段、backfill、删字段,3.0 实现闭环
如果你使用过生产级的 Milvus 集合,一定遇到过这个痛点:切换 embedding 模型时,要么停机双写,要么通过 ETL 周期重建集合。Schema 在线变更在 3.0 才真正形成闭环。
官方博客对 add_collection_field 和 drop_collection_field 的描述很关键:仅修改 manifest,不重写 data files。换言之,存量向量文件一个字节都不动,新增列仅是元数据层面操作。
3.0 的 backfill 区分了两种方向,需明确区分:
- Inner backfill(已 GA):针对函数计算的字段。例如为 text 列添加 BM25 函数,输出列对存量数据自动计算,无需双写。
- External backfill(仍在 roadmap,3.0 之后):值在 Milvus 外部计算。根据官方博客原文,流程为:take a snapshot → run Spark against the consistent view → compute a new column → write back → Milvus 增量索引。这条路径在 3.0 尚不能直接使用。
这一点容易被文档中模糊的措辞误导。请以官方博客(milvus.io/blog)为准,并参考本地 release notes:external backfill 在 3.0 尚未上线。对于很多人最关心的“热路径切换 embedding 模型”能力,那是 3.1 的事。
2.2 External Collection:从 zero-copy 读到完整 lakehouse 检索流程
External Collection 在 3.0-beta 引入,3.0.0 将其扩展为更完整的形态。简单来说:你可以在 Milvus 中直接检索已存在于 Iceberg / Parquet 中的数据,无需将数据复制进 Milvus。
3.0.0 的新增增强(来自 release notes):
- External fields 可作为 function output 字段,BM25、MinHash、text embedding 均可基于外部表数据计算。
- Refresh 支持 additive schema evolution,外部表新增列仅 patch 受影响的 segments,不会重建整个 collection。
- 新增
milvus-tableexternal format,Milvus Snapshot metadata 和 Storage V3 manifests 可作为外部源。
第三方实践(ideas.paasup.io)的复现确认了 zero-copy 可行:1,000 行 128-dim 随机向量 → Iceberg → External Collection → HNSW → 搜索返回 id∈[0,999]。Iceberg snapshot time-travel 也确认可挂载。
但有几个坑需要记住:
- External Collection 是 read-only 的。写入和 CDC 自动同步需等待 3.1 的
CDC-fresh external indexes。 - Schema 变更只能通过
tbl.overwrite()重写 Parquet + drop + recreate collection,Loon 无法为旧文件补 NULL 列。 external_source必须指向metadata.json文件路径,而非目录。- S3 URL scheme 必须是
s3://,不能使用minio://。
这对 Lakehouse 用户价值最大。如果你已有 Iceberg / Delta 数据湖,让 Milvus 在上面建索引并检索,可以省去 ETL 流水线。
2.3 TEXT 字段 + Sparse Index 重构:RAG 和 BM25 同时进化
3.0 将 TEXT 字段提升为一等公民。设计上的关键变化(来自 release notes):
- 长度限制在存储侧被移除,之前 TEXT 字段有长度上限,现在已无限制。
- 小于 64 KB 的值 inline 存储;≥ 64 KB 进入 partition-level LOB 文件(Vortex 格式),列仅存
(file_id, offset)引用。 - LOB 文件跨 segments 共享,compaction 时移动引用而非重写文本。
为什么这很重要:在 RAG 场景中,向量和源文本现在可以放在同一个 store 中一次 IO 取出,无需额外维护 blob store / S3 桶 / 文档数据库。3.0 之前,常见做法是将原文放 S3,向量存 Milvus,召回后还需再走一次 S3。多一跳 IO,多一份对象存储成本。
Sparse Index 这条线在 3.0 重新编写。引入了三个算法(release notes + arxiv 论文):
- SINDI(
arxiv.org/abs/2509.08395):针对 learned sparse embeddings。 - Block-Max WAND 和 Block-Max MaxScore(
block-max是这类剪枝算法的通用命名)。
厂商口径基准(release notes + LF AI & Data 博客多源一致):
- 启用新 index version 后,SINDI 是 sparse IP search 的默认算法。
- MaxScore 是 BM25 的默认算法。
- 压缩 BM25 index 大小约为 2.6 sparse index 的 1/3(同等 recall)。
- SINDI QPS 约为 MaxScore 的 10×(最坏情况约 5×)。
这些数字经厂商多源交叉确认,但仍属厂商内部基准。若要决定是否迁移,建议在自己数据集上跑一遍 reindex benchmark。
Multi-vector 这条线严格来说属于 StructArray 能力,与 Sparse Index 同属检索层但独立成线,这里列出是因为 trade-off 思路相近。3.0 给出了三种 trade-off(来自官方博客的 trade-off 表):
| 策略 | Stage-one representation | 代价 | 适用场景 |
|---|---|---|---|
| TokenANN | 每个 token 向量都索引 | 最高,精确 | 高区分度模型 / 短文档 |
| Muvera | 一文档一向量,随机投影 FDE | 中等,无需训练 | 长文档 |
| Lemur | 一文档一向量,MLP 压缩 | 最低,需训练 | 低区分度 / 视觉 patch |
官方称 Lemur 在多数数据集上 recall 与 TokenANN 持平或更优,但“多数”的具体数据集未列出。此判断也建议独立验证。
2.4 Woodpecker 成为默认 WAL:运维侧的变化
3.0 默认 WAL 已是 Woodpecker(替代 2.x 默认的 Pulsar / Kafka),这不仅是组件更换:
- 支持 3 种
storage.type:minio(默认)/local/service。 - 支持 standalone service 部署(distributed / cluster 模式),可独立扩缩、故障隔离、可观测。
这部分对运维的影响是直接的:减少 ZooKeeper / BookKeeper 组件栈,减轻 Pulsar 集群的运维负担。看起来是好事,但有两个已知问题必须先说明(详见下一节)。
Sparse Index 与 Multi-vector 检索策略算法对比
3. 落地前必须了解的 3 个门槛 + 2 个已知 bug
读完 release notes 觉得什么都好,这往往是踩坑的开始。3.0 的几个 opt-in 开关和社区已知问题,是上线前必须核对的。
3.1 Storage V3 默认关闭,但一旦开启便不可回滚
common.storage.useLoonFFI 默认是关闭的,这意味着依赖 Storage V3 的功能(Snapshot、TEXT 字段、External Collection 的 manifest 视图)默认不开启,需手动启用。后续版本将默认开启。
更关键的是:2.6 → 3.0 是兼容的,但一旦启用改变序列化数据格式的功能(如 Storage V3),回滚到 2.6 不再可能。我的判断是:将其视为 2.x 时代的小版本升级是危险的。生产灰度时,应先在 staging 环境开启 Storage V3,完成数据格式迁移,再考虑将 prod 流量切换。
3.2 新 index 需要手动上调 version
新的 sparse 算法(SINDI 等)需要先将 dataCoord.targetVecIndexVersion=10 和 dataCoord.targetScalarIndexVersion=4 手动调高,这是 opt-in 设置。release notes 明确说明后续版本将默认开启。
3.3 Woodpecker 的两个已知问题
独立部署的 Woodpecker 默认对接 local filesystem(minio / local 模式)。社区已有两个 issue 未在 3.0 release notes 中明确修复,对 standalone 部署影响最大:
- Issue #46067:切换 Woodpecker MQ + local storage 后,vector insertion rate 从 421 vec/sec 暴跌至 30 vec/sec(约 14 倍慢)。
- Discussion #45494(关联 Issue #45368):
docker compose down/up后启动报segment storage not writable,原因是 MinIO 中files/wp/残留 stale write.lock 文件。用户原文(英文):I had to reinstall Milvus and MINIO three times now。维护者tinswzy承诺在 v2.6.6 修复,但 3.0 是否同步修复未明确说明。
这两个 issue 都会影响 3.0 默认配置的 standalone 部署。在生产环境大规模上线前,强烈建议先在测试集群复现这两个场景,或至少确认自己使用的是 distributed / cluster 模式(独立 Woodpecker service),以避开 local storage 的坑。
Milvus 3.0 落地路径与 3 个门槛 2 个已知 bug 风险提示
4. 3.0 未解决、3.1 已规划的事项
3.1 路线图(来自官方 roadmap.md)已明确回应了几个 3.0 的边界:
- CDC-fresh external indexes:直接解决 External Collection 不能写的问题,使外部表增量同步到 Milvus。
- Apache Paimon 和 Delta Lake support:External Collection 当前默认面向 Iceberg,主流湖格式的覆盖需等到 3.1。
- UDFs(User-Defined Functions):在引擎内执行用户自定义逻辑。
- Time-travel / schema evolution / snapshot rollback 完整化。
- Predicate pushdown(page-index + bloom-filter pruning)、write-time primary-key dedup,性能侧继续打磨。
如果你的核心场景是湖数据需要写入和更新,那么 3.0 只是一个过渡版本,3.1 才是目标版本。
在商业生态上,3.0 之外还有一个值得关注的视角。TechTarget 引用 Moor Insights & Strategy 分析师 Mike Leone 关于 lake-native 安全责任的担忧,原话是:if Milvus is reading straight from a customer's tables, someone in security is going to ask who can see what。能力边界变了,安全治理的边界也随之改变,这不仅是 Zilliz 一家的问题,而是整个 lakehouse 阵营的开放性代价。
Pinecone / Weaviate / Qdrant 也都在朝低搜索延迟 + lake 互操作的方向发展。Snowflake / Databricks 已在云数仓端具备向量能力。与它们合作容易,因为它们接受标准列存;与其它 DB 供应商合作则因存储引擎差异,原话是 might be difficult(来自 blocksandfiles)。这是 Milvus 商业侧的隐形壁垒,技术能力是一回事,生态兼容是另一回事。
总结
将本次发布拆解来看:
- 主线是架构替换(云原生 → lake-native),底层是 Storage V3 / Loon 的 manifest 列存抽象。
- 真正改变工作流的能力:online schema 演进、External Collection、TEXT 字段、Sparse Index 重构、Woodpecker 默认 WAL,均围绕这条主线展开。
- 上线前必须了解的边界:Storage V3 开启后不可回滚 2.6;新 index 默认不开启;Woodpecker standalone + local storage 存在两个未确认修复的社区 bug。
- 外部 backfill、External Collection 写能力、Delta / Paimon 支持,需等到 3.1。
我的判断是:Milvus 3.0 这次 GA 的关键不在于功能数量,而是填平了 Beta 阶段挖的坑,稳定了上层能力的边界。lake-native 是故事,complete what the beta started 才是这个版本号背后的工作。
至于这个判断半年后是否依然成立,只需看一个信号:Snowflake / Databricks 是否会向量列作为一等公民。如果他们做了,Milvus 这一轮 lake-native 布局的 ROI 将被压缩一个量级;如果没做,Milvus 3.0 的窗口期就还在。在那之前,你在自己数据集上跑一遍 reindex 基准、复现 Woodpecker 两个 issue、再决定是否要将 embedding 模型热路径押注在 3.1,比什么都实在。
