土法炼钢兴趣小组的算法知识备份

【向量检索引擎】对象存储上的 Segment 布局:快照、索引与寻址代价

文章导航

分类入口
databasestorage
标签入口
#milvus#object-storage#minio#s3#segment#binlog#parquet#storage-v2#vector-engine

目录

Sealed 段「不可变且落在对象存储」是 第 3 篇 的定义;Query Node「从对象存储加载历史数据」是 第 7 篇 的前提。本文回答:对象存储里 大致存什么、flush/建索如何读写它,以及为何在 S3 类存储上 文件切分方式会支配延迟

本文是「向量检索引擎」系列第 6 篇(共 18 篇)。→ 系列目录

版本锚定:Milvus 2.6.x Architecture / Data Processing(A 级)。Storage V1→V2 布局演进引用官方工程博客(B 级),数字为原文陈述,非本机复现。


一、存储三件套里的对象存储

官方四层把持久化拆成:

组件 存什么 要求
Meta(etcd) schema 快照、消费 checkpoint;服务注册与健康检查 高可用、强一致、事务
WAL 提交前的写日志(Kafka / Pulsar / Woodpecker) 耐久、可 replay(第 5 篇)
Object storage 日志快照、标量与向量的索引文件、查询中间结果 便宜、可扩展;官方同时指出 高访问延迟、按请求计费

Milvus 默认常用 MinIO,并可部署到 AWS S3、Azure Blob 等。对象存储不是「又一块本地盘」,而是 高延迟随机打开的共享字节池——这决定了段文件布局必须减少小文件与 API 次数。


二、从 Growing 到对象上的 Sealed

Data Processing 路径(与第 3、5 篇对齐):

  1. Streaming Node 将 WAL 提交条目切成 Growing;
  2. flush 后数据持久化到对象存储,形成 不可变 Sealed
  3. Data Node 从对象存储加载该段快照,建索引,再把索引写回对象存储;
  4. Query Node 按 handoff 结果加载段数据与索引。

因此对象存储上至少有两类读者关心的对象族:

中间查询结果亦可落对象存储(Architecture)——多用于大结果或特定执行路径,本篇不展开为默认热路径。

flowchart LR
  wal["WAL commit"]
  grow["Growing"]
  obj["Object storage<br/>Sealed snapshot"]
  idx["Index files"]
  qn["Query Node load"]
  wal --> grow -->|flush| obj
  obj -->|DataNode build| idx
  obj --> qn
  idx --> qn

三、布局演进:按字段拆分 vs 按段整合

3.1 经典叙述:segment 内多 binlog

较早的工程叙述与源码路径仍大量出现 binlog 一词:段内用多份二进制日志/列文件记录插入与变更;compaction 处理 insert/delta binlog 与小段合并(历史博客 How to Compact Data in Milvus?,B 级)。Data Node compaction 源码计划里仍可见 SegmentBinlogs / FieldBinlogs 一类结构——说明 「段 → 字段 → 文件列表」 的元数据模型长期存在。

3.2 Storage V2:段级 Parquet 与 API 次数

官方工程博客 Data Addressing Deep Dive(2026-03,B 级)将对象存储性能归结为:

\[ \text{寻址代价} \approx \text{元数据访问次数} + \text{数据访问次数} \]

并对比 Milvus 存储布局演进(原文表格摘要):

方面 V1(按字段拆分) V2(按段整合)
文件组织 字段各自 binlog 以 segment 为单位整合
格式 自定义 binlog Parquet(文中亦提及可支持 Lance、Vortex)
统计信息 独立 stats_log 嵌入 Parquet footer
原文给出的量级感受 字段×段导致海量小文件、查询可触发极多 S3 API API 次数数量级下降、延迟从「分钟级感受」落到「秒级感受」

博客用「100 字段 × 1000 段」的思想实验说明 V1 小文件爆炸;V2 按段、按列组(column group)收敛文件数。这些倍数与「分钟/秒」是原文叙述,不是本站实测;读者应在自己的 MinIO/S3 上用段数×文件数核对 LIST/GET 次数。

3.3 与 2.6 写路径的关系

社区变更说明(如强制新写走 StorageV2 的 PR 叙述)表明 2.6 线将新写入统一到更新布局。本系列结论只取可核对的工程含义:

  1. 对象存储友好布局 = 减少小文件与按请求计费
  2. Query Node 加载与 Data Node 建索的输入输出都围绕「段在对象上的快照 + 索引对象」;
  3. 具体键前缀、列组切分以当时 release 的 storage 实现为准——排障时用对象浏览器/mc ls每段文件个数,比背路径模板更有用。

四、索引对象与数据对象的生命周期差

建索流程(Data Processing,A 级):

  1. Data Node 从对象存储加载待建索段快照到内存;
  2. 反序列化数据与元数据,调用索引构建(Knowhere,第 8 篇);
  3. 序列化索引,写回对象存储。

因此可能出现:

「磁盘上有索引文件」≠「Query Node 已加载该索引」——后者还取决于 Coordinator 的 data view(第 4、10 篇)。


五、与湖仓对象布局的一句对照

lakehouse 里 Iceberg/Parquet 优化的也是对象存储上的 清单 + 文件剪枝lakehouse/21 显示 Lance 在随机 take 上相对 Parquet 的优势。Milvus 的对象布局服务的是 ANN 段生命周期与索引文件,不是通用表格式事务。二者可共享同一对象桶,但 元数据权威不同——不要假设 Iceberg snapshot 与 Milvus segment 视图自动一致(第 16、18 篇)。


六、学术谱系、工程间隙、开放问题

6.1 谱系

问题 经典应对 在本篇的落点
共享存储上的小文件 合并文件、列组、清单 StorageV2/Parquet 段布局(B 级博客)
不可变数据 + 后台整理 LSM compaction、列存 merge Data Node compaction(第 10 篇)
寻址代价 元数据分层、缓存、剪枝 官方博客的 addressing 框架

6.2 工程间隙

6.3 开放问题

  1. 段大小、列组策略与 S3 计费模型如何联合优化?
  2. 索引文件与数据快照分桶/分存储类(IA/Archive)时,handoff 延迟如何建模?
  3. 与 Iceberg 共用桶时,生命周期策略误删索引前缀的防护?

七、小结

对象存储保存 Sealed 快照、索引与部分中间结果;etcd 管元数据,WAL 管提交。布局从「按字段碎文件」走向「按段整合(Parquet 等)」的核心动机是削减对象 API 次数。下一篇把多段候选如何收成一次响应:分布式 search 归并


参考资料

  1. Milvus Documentation v2.6.x, Architecture Overview / Storage/Computing Disaggregation(Object storage 职责与代价)。
  2. Milvus Documentation v2.6.x, Data Processing(flush、index building 读写对象存储)。
  3. Bill Chen, Data Addressing Deep Dive: From HashMap to Milvus, Milvus Blog, 2026-03(Storage V1/V2;B 级)。
  4. How to Compact Data in Milvus?, Milvus Blog, 2022(binlog/segment compaction 历史叙述;B 级)。
  5. 第 3、5、7 篇lakehouse/21

返回 系列目录 | 上一篇:Proxy 与 Coordinator | 下一篇:分布式 search 归并

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-06-30 · database / storage

【数据湖与开放表格式】对象存储语义与代价

对象存储不是网络版 POSIX 文件系统。本文用 S3 官方语义钉住四件事:强一致模型的边界、LIST 随对象数线性增长的代价、没有原子 rename(只能 copy+delete)、条件写(If-None-Match/If-Match)对提交协议的意义,并讲清 multipart 与对象不可改写。


By .