LanceDB Update/Upsert 机制源码深度解析
这篇文章是基于 LanceDB/Lance 源码的一次写路径与运维机制全链路拆解。核心问题与结论在 Copy-on-Write 架构下,行级更新本质上无法走原地改写,必须走“写新 + 标旧 + 提交新 Manifest”。Delete、Update、Merge Insert 虽然语义不同,但都围绕 Fragment 重…
LanceDB Update/Upsert 机制源码深度解析 源码版本:基于 lancedb v0.23.0 + lance v1.0.0(lance-core v1.0.0, arrow v56.2) 📌 本文范围:深入分析 LanceDB 的 Delete、Update、Merge Insert(Upsert)三大写操作的源码实现,以及 GC(Compact + Cleanup)机制和整体架构优劣。不涉及向量索引构建和查询优化。1. 引言:Copy-on-Write 架构下的更新挑战 LanceDB 基于 Lance 列式格式构建,采用 Copy-on-Write(CoW) 存储模型。与传统 RDBMS 的原地更新不同,Lance 中的每次修改都会产生新的数据文件,旧数据通过版本管理保留。 这引出一个核心问题:在 CoW 架构下,如何高效支持行级更新?graph TB subgraph traditional["传统 RDBMS: In-place Update"] A1["Page"] -->|"直接修改"| A2["Page ✏️ 已修改"] end subgraph lance["LanceDB: Copy-on-Write"] B1["Fragment v1"] -->|"标记删除旧行"| B2["Fragment v1<br/>+ DeletionVector 🗑️"] B1 -->|"写入新行"| B3["Fragment v2 🆕"] B2 --> B4["New Manifest 📋"] B3 --> B4 end style traditional fill:#fff3e0,stroke:#e65100 style lance fill:#e3f2fd,stroke:#1565c0 style A1 fill:#ffcc80,stroke:#e65100 style A2 fill:#ff8a65,stroke:#bf360c,color:#fff style B1 fill:#90caf9,stroke:#1565c0 style B2 fill:#ef9a9a,stroke:#c62828 style B3 fill:#a5d6a7,stroke:#2e7d32 style B4 fill:#ce93d8,stroke:#6a1b9a 🤔 Think About: CoW 意味着更新一行数据需要写入一个新文件并标记旧行删除。这种设计的代价是什么?好处又是什么?答案将在第 8 章揭晓。 本文结构:§2 架构背景 → §3 Delete → §4 Update → §5 Merge Insert → §6 并发控制 → §7 GC → §8 架构分析2. 架构背景:Lance 的 CoW 存储模型2.1 存储层级结构 Lance 的数据组织遵循 Dataset → Manifest → Fragment → DataFile 的层级结构。以本项目的 articles.lance 表为例,实际磁盘目录如下:articles.lance/ ← Dataset(一张表 = 一个目录) ├── _versions/ ← Manifest 文件(每个版本一个) │ └── 374.manifest ← 当前版本 v374 的元数据快照 ├── _transactions/ ← 事务日志 │ └── 373-682e2000-...-.txn ← 事务 373 的提交记录 ├── _deletions/ ← DeletionVector 文件 │ └── (空 = 当前无逻辑删除) ← 删除后会出现 .arrow 文件 ├── _indices/ ← 索引文件(每个索引一个 UUID 目录) │ ├── 77d0f6bf-.../ ← 某个 FTS 索引 │ │ ├── metadata.lance │ │ ├── part_214_docs.lance │ │ ├── part_214_invert.lance │ │ └── part_214_tokens.lance │ └── ... (共 29 个索引目录) └── data/ ← 数据文件(Fragment 的 DataFile) ├── 10011100...042fd44b.lance ← Fragment 0 的列式数据 (15 KB) └── 11101000...9838364.lance ← Fragment 1 的列式数据 (3.4 MB) 这些目录和文件对应的逻辑层级关系:graph TB D["🗄️ Dataset<br/><i>articles.lance/</i>"] M["📋 Manifest v374<br/><i>_versio…
正在初始化 WebAssembly 引擎…
首次编译原生模块可能需要数秒
就绪后,页面交互将以接近原生的速度运行