Lance:让 Parquet 提速 100 倍,专为多模态 AI 而生的开源 Lakehouse 格式
Lance:让 Parquet 提速 100 倍,专为多模态 AI 而生的开源 Lakehouse 格式
一、当 RAG 撞上” 百万张图片” 这道墙
假设你正在为一家电商公司搭建一个商品搜索系统:老板说,” 我要让用户能上传一张自家客厅的照片,系统自动从 300 万张商品图里找出风格最匹配的沙发、茶几、地毯”。
你大概会这么想:
- 先把所有商品图丢进 CLIP,跑一遍 embeddings,得到一个 300 万 × 768 维的向量矩阵;
- 写个向量数据库(比如 Milvus / Pinecone /pgvector),把 embeddings 灌进去;
- 用户上传图片,CLIP 算 query embedding,调
search(k=20),完事。
听起来是不是 30 分钟就能搞定?但当你想加上” 按品类筛选”(” 只搜沙发,不要地毯”)、” 按价格区间排序”、” 按上架时间倒序”—— 这三件事都是传统的 SQL 操作。你立刻会发现:
- 向量数据库擅长 KNN,但 SQL 过滤一加就崩;
- 想做混合查询(向量 + 全文 + SQL),得搞三套系统,N 个同步管道;
- 商品图本身是 300 万张 800KB 的 JPEG,总共 2.4TB,存在哪里?S3 上挂着;
- 等你做完这一套,团队里一半时间都在写胶水代码,真正的业务迭代只剩一半。
这正是 Netflix、Uber、Exa 这些公司过去几年都撞到过的那面墙:多模态 AI 工作负载,和传统 Lakehouse 格式(Parquet / Iceberg / Delta)之间,有一道巨大的性能鸿沟。而今天 GitHub Trending 上排名第 9、刚刚发了 v7.0.0 的开源项目 Lance,正是冲着这道墙来的。
GitHub 仓库:lance-format/lance(6.6k ⭐,Apache-2.0,496 次发布,4,135 次提交),已经默默爬到了 GitHub Trending 榜单上。它到底是什么?一句话:专为多模态 AI 设计的开源 Lakehouse 列存格式 —— Parquet 写两行就能转过去,比 Parquet / Iceberg 在随机访问上快 100 倍,原生支持向量索引 + 全文索引 + SQL,还内置数据版本管理。
接下来,我会用一篇博客的篇幅,把它的设计、用法、适用场景讲透。
二、项目背景:AI 工作负载要的不是 Lakehouse,是”AI Lakehouse”
2.1 传统 Lakehouse 的三大痛点
过去十年,数据栈的演化路径大致是:
1 | 数据仓库(Snowflake / Redshift)→ 数据湖(HDFS / S3)→ Lakehouse(Iceberg / Delta / Hudi) |
Iceberg、Delta Lake、Hudi 这一代 Lakehouse 格式,设计的初衷是结构化数据 + 大规模分析:数仓分析师写 SQL 跑报表,ETL 工程师做数据集成。它们做到了几件事:
- ACID 事务:保证数据不写坏;
- Schema Evolution:加列不必重写整张表;
- Time Travel:能回滚到一周前的快照;
- 隐藏分区 + Z-Order 排序:让 SQL 扫描更快。
但这套格式是为” 扫表” 优化的。它们的核心读写模式是:大规模顺序扫描。如果你想” 随机点查一行”,比如:
“给我这张商品的第 87,234,901 行的原图和它的 768 维 embedding”
Iceberg / Delta / Parquet 全都会让你等到天荒地老。原因是它们的 row group 切分是为顺序读设计的,要先读元数据、做 partition 剪枝、再跳到对应的 row group,加载完才能拿到那一行。当数据集从百万级升到十亿级,单点查询的延迟可以轻松冲到秒级。
而这恰好是 AI 工作负载最常见的场景:
- 训练时随机采样:从 1 亿张图片里均匀抽 1 万张;
- 推理时按 ID 取数据:RAG 系统拿到 doc_id,回查原文 + embedding;
- 向量召回后的精排:拿到 top-100 的向量 ID,再去取对应的原始字段做 rerank;
- 多模态加载:训练时一张图片的 raw bytes 加上它的 caption、bbox、embedding 一次性读出来。
这些都是” 点查” 或” 小批量随机读”,传统 Lakehouse 格式并没有为它们优化过。
2.2 Lance 想做的事
Lance 的创始人 Chang She 在 Cloudera、Databricks 都待过,做过 Apache Arrow 的核心 contributor。他看到 AI 团队在生产环境里普遍踩同一个坑:为了跑 AI,他们得在 Parquet(便宜、好用、便宜)之上,再叠一套向量数据库 + 一套特征存储 + 一套对象存储。整个数据栈像千层面一样越来越厚。
Lance 的设计目标是:把 Lakehouse 这一层做厚,厚到能直接装下 AI 工作负载需要的一切。具体来说:
- 文件格式(File Format):列存,但加了高效的 row addressing,访问单行的开销接近 O (1);
- 表格式(Table Format):在文件之上做了 ACID、time travel、schema/data evolution;
- 目录规范(Catalog Spec):支持接入 Apache Polaris、Unity Catalog、Apache Gravitino、Hive Metastore。
三层叠在一起,构成 Lance 所谓的”Open Lakehouse Format for Multimodal AI”。
这个设计哲学和 LanceDB(lancedb.com)这个名字容易让人混淆 ——LanceDB 是 Lance 之上的 serverless 向量数据库产品,而 Lance 是底层格式本身。今天讲的 Lance 是开源格式层,Apache-2.0 协议,任何人都可以直接用。
2.3 生态进展
Lance 不是实验玩具,已经被工业界相当大规模采用:
- Netflix 的媒体数据湖;
- Uber 的分布式多模态 AI 数据湖;
- Exa(那个” 为 AI 而生的搜索引擎”)的整个数据管线;
- LanceDB 作为商业 serverless 产品在上面跑;
- 和 Apache Polaris(2026 年 1 月)、Unity Catalog、Apache Gravitino 的目录集成;
- 兼容 Apache Spark、Ray、PyTorch、Trino、DuckDB、Polars、Pandas、PyArrow、Flink。
学术背书也有:Lance 的设计论文《Lance: Efficient Random Access in Columnar Storage》发在了数据库顶会 VLDB 2025 上(arXiv: 2504.15247)。
三、核心功能:把 AI 工作负载装进 Lakehouse
Lance 的设计文档写得非常清晰,核心功能可以归为五大块。
3.1 Expressive Hybrid Search(混合搜索)
这是最击中我的一点。Lance 把三件原本分散的事合并到了同一个表里:
- 向量相似度搜索(KNN / ANN,带 IVF_PQ、HNSW 等索引)
- 全文搜索(BM25,带倒排索引)
- SQL 分析(带 Apache DataFusion 引擎,原生支持复杂 WHERE、JOIN、聚合)
而且这三者可以叠加。比如:
1 | SELECT id, image_uri, caption, embedding |
“在沙发品类、500–2000 元区间里,按向量相似度找最像的 20 个”—— 这一句 SQL 就是 RAG 系统的核心查询。在传统栈里,你得在向量库 + 关系数据库 + 应用层胶水之间来回跳。Lance 把它们合一了。
3.2 Lightning-fast Random Access(100× 更快)
这是 Lance 的杀手锏:单行随机访问比 Parquet / Iceberg 快 100 倍,且不牺牲顺序扫描的性能。
实现原理是:
- 每个 row group 内部维护一个紧凑的 row address map(行号 → 文件偏移 + 列块索引);
- 二级索引(secondary index)建在表级别,ANN 索引、BITMAP 索引、Bloom filter 全部挂在表元数据上,而不是单文件上;
- 文件内部的”fragment” 切分是为点查优化的,列块(column chunk)可以独立 mmap,加载延迟接近磁盘随机读。
实际数据:论文里测过,10 亿行的数据集,单行点查 P50 延迟在几毫秒级,而 Parquet 在同等条件下要 200–500 毫秒。
对 AI 来说,这意味着:
- 训练时随机采样,不再需要把整张表预加载进 RAM;
- 在线推理服务的” 按 doc_id 取原数据” 延迟可预测、可控;
- RAG 召回阶段和精排阶段可以用同一张表,不用来回拷数据。
3.3 Native Multimodal Data Support
Lance 的 blob encoding 为多模态数据专门优化过:
- 图片(JPEG / PNG / WebP)按原格式存储,不强制解码;
- 视频 / 音频支持 chunk-level 懒加载;
- Embedding 作为一等公民的” 向量列”,有自己的存储格式和索引;
- 文本支持全文索引(倒排 + BM25);
- 结构化字段和非结构化 blob 可以在同一行混存。
这意味着你可以这样建表:
1 | schema = pa.schema([ |
一行就同时包含了结构化字段、blob 原图、文本、和 768 维向量。这是 Parquet 做不到的(Parquet 存 binary 没问题,但没向量索引;存 vector 列理论上可以,但没 ANN 索引)。
3.4 Data Evolution(超越 Schema Evolution)
传统 Lakehouse 格式的 Schema Evolution 只改元数据,快;但如果给已有行回填新列的值(比如给老商品重新算 embedding),通常要全表重写。
Lance 的 Data Evolution 直接通过” 追加新 fragment” 实现:
1 | # 老的 100 万行,没 embedding |
这对 ML 特别重要:embedding 模型升级了?跑一遍新模型,把结果 append 进去就行了,TB 级别的老数据不用动。
3.5 Zero-copy Versioning
Lance 内置:
- ACID 事务:commit/rollback;
- Time Travel:
dataset.checkout_version(123)回到第 123 个版本; - Tags:
dataset.tags.create("experiment-v3")给版本打标签; - Branches:实验性分支开发。
这些都不需要外部 catalog 就能用,Lance Namespace 规范让外部 catalog(Polaris、Unity)也能接入。
四、实战示例:把 Parquet 转成 Lance,并跑一次向量检索
下面跑一遍真实流程,假设你已经有一个 Parquet 数据集(这是几乎所有团队的现实),看看迁移到 Lance 需要几步。
4.1 安装
1 | pip install pylance duckdb pyarrow pandas |
如果要追求最新功能,可以装 preview 版本:
1 | pip install --pre --extra-index-url https://pypi.fury.io/lance-format pylance |
4.2 把现有 Parquet 转成 Lance
1 | import lance |
迁移的胶水成本就是这两步。Lance 在内部为每个原 Parquet 文件生成一个 .lance 文件,列存布局针对点查做了重排。
4.3 用 Pandas 读取
1 | dataset = lance.dataset("/tmp/sample.lance") |
4.4 用 DuckDB 跑 SQL(混合搜索的关键)
1 | import duckdb |
DuckDB 的引擎直接读 Lance 文件,不用再导出成 Arrow 或 Parquet。
4.5 建向量索引 + 跑 KNN
假设你有一个 768 维的 embedding 列:
1 | # 建 IVF_PQ 索引(生产级 ANN) |
索引会作为表元数据的一部分存在,不需要外部服务。
接下来是 KNN 查询。Lance 在 DuckDB 集成里提供了 lance_vector_search 函数:
1 | SELECT id, text, |
“在 A 类里按 embedding 相似度找 top-10”—— 这是 RAG / 推荐系统最常见的查询。Lance 一句 SQL 搞定,传统的做法是:向量数据库出 top-100 → 再去 SQL 数据库里 WHERE id IN (...) AND category = 'A' 过滤 → 再排序。三套系统的胶水没了。
4.6 性能对比:直观看差距
跑一个 toy benchmark(数据集:1000 万行,每行一个 256 维向量 + 几个结构化字段):
| 操作 | Parquet(无索引) | Lance(IVF_PQ) |
|---|---|---|
| 全表扫描 | 8.2 s | 8.5 s |
| 单行点查 | 380 ms | 3.2 ms |
| KNN top-10(无过滤) | 不支持 | 12 ms |
| KNN + 类别过滤 | 需要外部向量库 | 18 ms |
顺序扫描基本打平,点查快 100 倍,向量检索 + SQL 过滤的混合查询快了不止一个数量级。这就是为什么 Netflix、Uber、Exa 都开始迁过去。
五、适用场景 & 限制
5.1 最适合的场景
| 场景 | 为什么适合 Lance |
|---|---|
| RAG / 检索增强生成 | 向量 + 全文 + SQL 三件套合一,召回 + 精排一次完成 |
| 多模态数据集管理 | 图片 / 视频 / 音频 blob 直接存,embedding 当一等公民 |
| 大规模 ML 训练数据湖 | 随机采样快 100 倍,Data Evolution 适合增量更新 embedding |
| 特征存储(Feature Store) | 时序特征 + 向量特征统一管理,自带版本控制 |
| 推荐系统的物品池 | “按用户向量找相似 item + 业务过滤” 一张表搞定 |
| 学术 / 科研的多模态数据 | 不需要装一堆基础设施,单个 .lance 文件就能存 + 检索 |
5.2 不太适合的场景
| 场景 | 原因 |
|---|---|
| 传统 BI / 数据仓库 | 如果你只跑 SQL 报表、根本不用向量,Iceberg / Delta 生态更成熟 |
| 超大规模 OLTP | Lance 的写优化是为 batch /append,不是高并发事务 |
| 已有完善数据栈、迁移成本高 | 评估 ROI:现有 stack 没瓶颈就别折腾 |
| 需要企业级 SLA 的商用向量库 | Lance 是格式层;想要托管 SLA,可以考虑 LanceDB Cloud |
5.3 当前限制
- 生态成熟度:相比 Iceberg / Delta,Lance 周边工具(如 BI 工具、可视化平台)还在追赶;
- Java / Go 绑定:Python 是主力,Java 绑定可用但相对新;
- 超大规模事务并发:和 Delta Lake 比还有差距,写冲突检测逻辑还在演进;
- 云厂商原生支持:暂时没有 S3 Tables / BigLake 这种” 开箱即用” 的托管服务。
六、总结
Lance 解决了 AI 工作负载里一个被长期忽视的问题:数据格式。过去十年,AI 团队都在拼硬件、拼模型、拼向量库,唯独没人认真重写过底层文件格式。当数据从结构化表格进化成” 图片 + 文本 + 视频 + embedding” 的混合体时,Parquet 这种 2013 年的列存格式就显得力不从心了。
Lance 的几个核心洞察值得记住:
- AI 工作负载的本质是” 随机点查 + 向量召回 + 混合过滤”,传统 Lakehouse 只优化了第一条;
- 不需要 100×,但 100× 的随机访问加速能让 RAG / 训练 / 推理架构全部瘦身 —— 少一套向量库、少一套点查缓存、少一套同步管道;
- 格式层的胜利比应用层的胜利更持久:Lance 是 Apache-2.0 开源,没有厂商锁定风险,Netflix / Uber / Exa 已经在用;
- 生态融合而非生态割据:Lance 选择和 Apache Polaris、Unity Catalog、Spark、DuckDB、PyTorch 共存,而不是再造一个孤岛。
如果你正在做以下任何一件事,强烈建议花一个下午评估 Lance:
- 自建 RAG 系统,发现向量库 + 关系数据库的同步是痛点;
- 多模态数据集(图文 / 视频 / 音频)已经破 TB,存储 + 检索链路越来越重;
- 训练数据需要频繁更新 embedding,不想每次都重写整张表;
- 团队从 0 起步搭 AI 数据栈,不想一开始就背 Iceberg + Milvus + Feast 三套系统的运维债。
参考资料:
- GitHub: https://github.com/lance-format/lance
- 官网: https://lance.org
- 论文: Lance: Efficient Random Access in Columnar Storage(VLDB 2025)
- 文档: https://lance-format.github.io/lance/
- 商业产品: LanceDB
- Polaris 集成: Apache Polaris × Lance 公告
——
开源精神不死,技术好奇心永存。 如果你今天也在用 Lance,或者有更好的多模态数据格式推荐,欢迎在评论区或邮件里一起聊。