DeepSeek总结的在 DuckDB 中试驾 Lance 数据湖仓格式

来源:https://duckdb.org/2026/05/21/test-driving-lance

在 DuckDB 中试驾 Lance 数据湖仓格式

作者: LanceDB 团队和 Guillermo Sanchez
日期: 2026-05-21
阅读时间: 11 分钟

摘要: Lance 是一种开放的数据湖仓格式,其设计面向 AI 工作负载。LanceDB 和 DuckDB Labs 合作,让您可以直接从 DuckDB SQL 中进行快速的向量和混合搜索,而无需离开您的分析工作流。在这篇文章中,我们将解释 Lance 是什么,如何在 DuckDB 中使用它,当然,还会展示一些基准测试结果。

通过 lance 扩展,DuckDB 用户可以使用相同的熟悉 SQL 接口(通过 CLI 或 SDK)查询 Lance 数据集,同时增加对 AI 和检索工作负载的能力。本文重点介绍了 Lance 如何成为需要支持向量存储和查询、丰富的表操作、面向 AI 的访问模式,同时还能支持大规模、扫描友好的分析工作负载的工作负载的一个好选择。而借助 DuckDB,用 SQL 查询这些类型的数据集变得非常简单。

在这篇博客中,会提到一些"检索工作负载"、"AI 数据模式"或"AI 数据集"。这里的"检索工作负载"是指通过相似性或关键词相关性(如向量搜索和全文搜索)来查找行的查询,而不是通过精确过滤或聚合。"AI 数据模式"是指将嵌入、图像或音频与标量元数据混合在一起的数据集。

什么是 Lance?

Lance 是一种为现代机器学习和 AI 工作负载设计的开放数据湖仓格式。与 Parquet 不同,Lance 同时是一种文件格式、一种表格式和一种轻量级目录规范。在表格式层面,Lance 通过 MVCC 和类似 ACID 的语义支持版本控制、模式演化、索引和事务性更新。在实践中,这意味着 Lance 是为随时间变化且不仅仅需要只读扫描的数据集而构建的。

这一点很重要,因为许多 AI 数据集不再只是标量值的行。它们通常包含嵌入、长文本、图像、音频、用于过滤的元数据以及用于检索的索引。适用于这些工作负载的格式需要做的不仅仅是高效存储和扫描列。它还需要支持搜索、更新和生命周期操作,而无需强迫用户管理多个不同的系统。

对于来自 Parquet 的用户来说,其思维模型仍然熟悉:开放格式的列式数据,使用标准的分析工具进行查询。Lance 基于片段(fragment)的布局将数据存储在小型的列式块中。这种设计实现了高效的随机访问,而无需在扫描性能或内存利用率方面进行权衡,这在历史上对于列式格式来说是难以实现的,Lance 团队在 2025 年关于自适应结构编码的论文中对此进行了研究。

在数据演化方面,添加列或用新数据回填现有行只会写入新文件,而不会触及现有文件。这使得模式更改在实践中变得轻量级,这对于增量添加列的工作流非常有用,例如将派生特征或嵌入附加到现有数据集中。

DuckDB 的 Lance 扩展

lance 扩展将 Lance 作为基于 SQL 的工作流的一部分引入 DuckDB。您可以直接读取 Lance 数据集,通过 COPY 写入它们,将它们作为表命名空间附加,构建索引,并使用常规的 DuckDB SQL 查询它们。此外,该扩展通过 SQL 表函数公开了 Lance 原生的搜索功能。

这与 DuckDB 已有的使用方式自然契合:作为一个单一的、嵌入式的 SQL 查询引擎,可以对许多不同的数据源和文件格式进行操作。通过 Lance 扩展,DuckDB 仍然是熟悉的查询引擎,而 Lance 在底层提供存储、索引和搜索功能,这在您的数据是多模态且包含嵌入时尤其有益。

使用示例

安装和使用扩展很简单:

sql 复制代码
INSTALL lance;
LOAD lance;

SELECT *
FROM 'path/to/dataset.lance'
LIMIT 10;

DuckDB 也可以直接写入 Lance 数据集:

sql 复制代码
COPY (
    SELECT *
    FROM (
        VALUES
            (1::BIGINT, 'duck', [0.9, 0.7, 0.1]::FLOAT[3]),
            (2::BIGINT, 'horse', [0.3, 0.1, 0.5]::FLOAT[3]),
            (3::BIGINT, 'dragon', [0.5, 0.2, 0.7]::FLOAT[3])
        ) AS t(id, animal, vec)
) TO 'path/to/out.lance' (FORMAT lance, mode 'overwrite');

一旦数据进入 Lance,DuckDB 就可以使用 Lance 原生搜索操作符进行查询。例如,混合搜索在一个 SQL 查询中结合了向量相似度和关键词相关性:

sql 复制代码
SELECT id, text, _hybrid_score, _distance, _score
FROM lance_hybrid_search(
    'path/to/dataset.lance',
    'vec',
    [0.1, 0.2, 0.3, 0.4]::FLOAT[4],
    'text',
    'puppy',
    k = 10,
    prefilter = false,
    alpha = 0.5,
    oversample_factor = 4
)
ORDER BY _hybrid_score DESC;

该扩展还公开了用于向量相似度搜索的 lance_vector_search(...) 和用于全文搜索的 lance_fts(...),以便用户可以选择适合其工作负载的检索模式。

如果您希望使用表式访问而不是基于路径的访问,您可以将一个目录作为 Lance 命名空间附加:

sql 复制代码
ATTACH 'path/to/dir' AS ns (TYPE lance);

SELECT count(*)
FROM ns.main.my_table;

索引创建也是通过 SQL 完成的。例如,可以直接在 Lance 数据集上创建向量索引:

sql 复制代码
CREATE INDEX vec_idx ON 'path/to/dataset.lance' (vec)
USING IVF_FLAT WITH (num_partitions = 1, metric_type = 'l2');

该扩展的功能远不止于只读扫描。在当前实现中,DuckDB 可以:

  • 通过直接路径扫描读取 Lance 数据集
  • 使用 COPY ... TO ... (FORMAT lance) 写入和追加 Lance 数据集
  • 使用 SQL 函数运行向量、全文和混合搜索
  • 附加本地目录或通过 REST 命名空间附加自定义目录
  • 在附加的命名空间中创建、更新、删除、合并和更改表
  • 创建和管理向量、标量和全文索引
  • 运行诸如压缩、清理和索引优化等维护操作

请注意,这个扩展不仅仅是一个文件读取器,它还为 DuckDB 用户提供了一种从 SQL 内部将 Lance 作为操作性表格式使用的方式。

为什么选择 Lance 和 DuckDB?

Lance 和 DuckDB 的结合引人注目,原因有三。

首先,它为用户提供了一个 SQL 界面,同时用于分析和检索。同一个 DuckDB 工作流可以扫描数据集、过滤它、与其他表连接、计算聚合,然后在结果集上运行向量搜索或混合搜索。这非常适合检索只是更大分析流程中一步的 AI 应用程序。

其次,Lance 是一种超越传统分析的表格式。许多 AI 流程需要版本化的数据集、更新、删除、MERGE 式更改、索引管理和模式演化。DuckDB 扩展通过 SQL 公开了这些功能,这意味着用户仅仅因为他们的数据集不仅仅是服务于分析读取,就无需离开 DuckDB 环境。

第三,该工作流从本地文件扩展到远程存储,而无需改变思维模式。您可以从本地 lance 数据集开始,然后迁移到对象存储。

该扩展还支持 REST 命名空间,因此 DuckDB 可以连接到远程 Lance 目录(包括 LanceDB Enterprise),并将其视为附加的数据库。这使得从本地到远程存储的演进感觉上是渐进式的,而不是破坏性的。

总而言之,DuckDB 仍然是熟悉的 SQL 引擎,而 Lance 增加了存储和索引功能,当同一个数据集同时支持分析和检索时,这些功能尤其有用。

性能实验

LAION 是一个从公共网络抓取的图像/标题配对开放数据集,最初发布是为了支持像 CLIP 这样的模型的研究,这些模型学习图像和文本的共享嵌入空间。完整版本包含数十亿个配对。在这个实验中,我们使用了 Hugging Face Hub 上的 lance-format/laion-1m 子集,该子集易于在本地复现。

每一行都包含一个标题、一个 768 维的 CLIP 图像嵌入、原始图像字节,以及像宽度、高度和 NSFW 标志这样的标量元数据。这种在一个表中混合标量、文本、向量和 blob 数据的方式使其成为比较格式的有用工作负载,并且它在结构上不同于传统用于分析基准测试的宽扁平模式(如 TPC-H 或 ClickBench)。

基准测试使用的公共 Hugging Face 导出目前在本地物化了 69,632 行,而不是完整的百万行源数据集。运行程序首先下载公共的 Parquet 分片,然后从相同的基线构建所有本地构件:一个 LZ4 压缩的 Parquet 文件、一个带索引的 DuckDB 数据库和一个 Lance 数据集。生成的文件在多次运行中重复使用,因此初始下载是唯一需要联网的步骤。

实验在一台配备 10 核 M1 Max CPU 和 32 GB RAM 的 Apple MacBook Pro 上运行,使用 DuckDB 1.5.2。

基准测试使用 DuckDB 作为查询引擎,对以下三种存储格式进行了测试:

  • Parquet: DuckDB 直接扫描 LZ4 压缩的 Parquet 基线,无辅助索引。
  • DuckDB 索引版 : 将相同的基线加载到 DuckDB 表中,并在其上叠加 DuckDB 的 vss(HNSW)和 fts 扩展,以及在过滤列上添加标量索引。这是典型的"在 DuckDB 中自己构建"的技术栈。
  • Lance 原生版 : 将相同的基线写入带有向量索引、全文索引和原生 blob 存储的 Lance 数据集,并通过 DuckDB lance 扩展进行查询。

尽管不同存储/索引后端的 SQL 有所不同,但工作负载按任务在三条路径上对齐:

  • fts: 通过对标题文本进行关键词搜索来查找行。
  • vector_exact: 对 CLIP 嵌入列执行最近邻搜索,不使用近似向量索引。
  • vector_indexed: 使用可用的向量索引对相同的嵌入列执行最近邻搜索。
  • hybrid: 将文本搜索和向量搜索结合到一个检索查询中,从两种信号中返回排名最佳的结果。
  • blob_read: 为选定的行获取图像字节,这涉及对大型二进制值的随机访问,而不仅仅是标量或向量列。

每个工作负载默认运行五次,下表报告平均值。完整的脚本和 SQL 查询位于 laion_1m 基准测试目录中。

冷启动结果

下表在全新的 DuckDB 进程中冷启动运行每个工作负载,因此它包含了进程启动、文件打开和首次查询的成本。这最接近一次性脚本或 cron 作业所看到的情况。

工作负载 Parquet DuckDB 索引版 Lance 原生版
fts 12 毫秒 11 毫秒 21 毫秒
vector_exact 695 毫秒 61 毫秒 89 毫秒
vector_indexed 761 毫秒 104 毫秒 12 毫秒
hybrid 465 毫秒 80 毫秒 17 毫秒
blob_read 1559 毫秒 271 毫秒 278 毫秒

在冷启动运行中,Lance 在 vector_indexedhybrid 工作负载中表现突出。DuckDB 自己的格式在 vector_exactfts 中表现出色,而 blob_read 工作负载则基本持平。Parquet 在向量搜索或 blob 读取方面未做优化,但在由正则表达式驱动的简单文本搜索上表现良好。

热启动结果

热启动结果是在静默预热后,在单个 DuckDB 会话中运行所有工作负载得出的,因此缓存、内存映射页面和加载的索引已经准备就绪。

工作负载 Parquet DuckDB 索引版 Lance 原生版
fts 12 毫秒 10 毫秒 7 毫秒
vector_exact 703 毫秒 30 毫秒 50 毫秒
vector_indexed 755 毫秒 2 毫秒 5 毫秒
hybrid 471 毫秒 11 毫秒 8 毫秒
blob_read 1484 毫秒 266 毫秒 276 毫秒

当缓存和索引已经预热时,DuckDB 和 Lance 在检索工作负载上都比使用 Parquet 快得多。

结论

Lance 是开放数据湖仓格式领域相对较新的成员。它是为那些随时间变化、包含的不仅仅是标量值、并且需要与传统扫描工作负载一起支持搜索和检索的数据集而设计的。通过 DuckDB 扩展,这些功能可通过 SQL 获得,同时保留了熟悉的嵌入式工作流。基准测试结果,特别是在冷启动运行中,反映了对于向量和混合搜索而言,Lance 是 DuckDB 自身格式的一个很好的替代方案。

DuckDB 中对 Lance 的支持是通过 DuckDB Labs 和 LanceDB 之间的合作实现的。

相关推荐
试剂界的爱马仕10 小时前
《古董局·终局5:潮生》第 2 章:镜子的天赋
大数据·人工智能·算法
Kingairy10 小时前
Agent的发展阶段
人工智能
啦啦啦_999910 小时前
CNN 卷积神经网络
人工智能·神经网络·cnn
TMT星球10 小时前
伴鱼袁志强:AI个性化学习告别“推题时代”,教育 AI Harness 进入学习全过程
人工智能·学习
PaperData10 小时前
2017-2025年中国10米分辨率土地利用/覆盖栅格数据(from Esri LULC)
数据库·数据分析·学习方法
小二·10 小时前
LangGraph 多智能体实战:从零搭建 Multi-Agent 协作系统
java·开发语言·数据库
Rocktech_ruixun10 小时前
从场景落地到技术迭代:服务机器人迈入规模化商用爆发期
大数据·人工智能
Yeats_Liao10 小时前
物联网接入层技术剖析(三):epoll在JVM中的映射
java·linux·jvm·人工智能·物联网