Rebas Daily PERSONAL AI DAILY — 自动选题 · 核查 · 撰写 NO.095 — 2026-10-07
NEWS 约 6 分钟

DuckDB搬数:难点在入口

把一年业务数据搬进 DuckDB,真正难的不是查询,而是设计一条快、稳、团队养得起的数据入口。

IMAGE — DuckDB Blog

你要把一仓库文件搬到隔壁房间。新房间整理东西很快,麻烦却出在门口:一次搬一件太慢,先堆到走廊又没有空间,借来的传送带虽快,却没人保证以后还能修。这正是一次 MongoDB 到 DuckDB 搬迁遇到的问题。它值得关注,因为嵌入式分析真正落地时,决定体验的往往不是数据库能多快地算,而是数据能否顺利进去。

本文依据 DuckDB 官方博客刊登的一篇用户客座文章。所有速度均为作者在特定环境中的测试或经验,材料没有披露硬件、软件版本、缓存状态、重复次数和波动范围,因此不能视为通用基准。

查询已经优化,报表还是等不起

这家公司把客户的漏洞数据存在 MongoDB。MongoDB 是文档数据库——每条记录可以像一份层层嵌套的表单,适合业务系统灵活读写。但当任务变成扫描大量记录、分组和统计时,它与分析型数据库的长处不同。

随着数据增加,公司花了几个月优化查询、调整数据结构并增加索引。效果有所改善,但部分分析仍要数十秒,例如统计已关闭和未关闭的漏洞,或找出最近六个月漏洞最多的十个业务部门。Excel 导出更突出:作者称,导出 5 万条记录需要 2—3 分钟,而且耗时不稳定。

团队于是计划把一年的数据导入另一套数据库。目标是分析查询不超过 1 秒,5 万条记录在 10 秒内导出为 Excel;更久的任务转到后台。注意,这是项目要求,不是文章已经完整证明的最终成绩。

新数据库还必须和 MongoDB 共用一台服务器,持续开发、免费、开源,并能在有限资源下运行。作者认为 DuckDB 符合这些条件。DuckDB 是嵌入式分析数据库——它通常直接运行在应用或分析脚本的进程中,不必再维护一台独立数据库服务器,擅长扫描和汇总大量数据。

最顺手的入口,为什么反而没选

团队先试了 DuckDB 的 mongo community extension,也就是由社区维护的 MongoDB 扩展。概念验证很快搭好。文章展示的一次特定导入操作,在匿名样本上耗时 55 秒。这个数字对应文中的具体 SQL 流程,不能简化成“MongoDB 数据导入 DuckDB 只需 55 秒”。

样本是从生产数据显著缩小后得到的匿名数据集,包含 485,168 条记录和 24 个字段。其中 description 与 references 两个字符串字段,中位长度分别为 5,000 和 2,500 个字符,个别记录可达 32,000 个字符。也就是说,它不只是几十万行短数字,里面还拖着大量长文本。

据作者报告,在这套概念验证中,GROUP BY 和 COUNT 等分组计数查询低于 100 毫秒,5 万条记录的导出低于 5 秒;但读取大文本列时性能会下降,作者为此提交了问题。数据排序还能继续改善查询表现,采用最新的存储兼容版本也明显缩小了数据库文件。不过文章没有给出缩小幅度。

单看接入难度和作者的测试,这个社区扩展最省事,性能也最好。团队最终仍放弃了它。他们担心 DuckDB 更新很快,而社区扩展可能没有同步升级。一旦扩展无法继续构建,公司要么停留在旧版 DuckDB,要么自己维护一个 C++ 分支。团队更熟悉 Java,也希望把导入管道复用于其他内部数据源,因此不愿长期背上陌生的 C++ 维护工作。

这是一项很现实的取舍:今天最快的入口,如果明天没人维护,未必是总体成本最低的入口。

逐条塞进去,输在了搬运方式

团队随后改用 Java。最直接的办法是通过 JDBC——Java 访问数据库的标准接口——批量执行 INSERT,把记录写入 DuckDB。为方便并行处理,他们把一年按天切成批次,每个工作线程分别从 MongoDB 读取一天的数据。

供稿没有给出这一方案及后续 Appender 方案的完整计时,只明确说两者仍然太慢。中间文件路线也走不通:先把 MongoDB 数据导出成 NDJSON、CSV 或 Parquet,再让 DuckDB读取,本来颇有希望,却因为磁盘放不下额外的数据副本而终止。

据 DuckDB 官方博客中的项目叙述,作者接近放弃时转而阅读社区扩展源码,才找到关键:不要让 Java 更卖力地逐行推数据,而要把数据源包装成 table function。

表函数可以理解为一张由程序现场生成的表。DuckDB 向它索取一批批记录,再像读取普通表一样执行 SQL。在这个项目里,Java 负责把 MongoDB 数据整理成这样的入口,DuckDB则主动、并行地拉取数据。搬运方式从“应用逐件送货”变成了“数据库按自己的节奏组织取货”。

博客称,最终的纯 Java 管道在真实数据上的导入速度追平了社区扩展,同时更符合团队已有的维护能力。作者还与 Duck Labs 团队准备了简化示例,放在 GitHub 仓库 staticlibs/duckdb_java_data_import;作者称其性能特征与实际代码“大致相符”。不过“大致”没有量化误差,不能据此推定示例就是生产环境复现。

值得看的不是又一次速度竞赛

这次实践揭示了嵌入式分析里容易被低估的一层:分析引擎可以和应用运行在同一台机器,用户也可以直接在业务界面看报表,但原始数据仍要跨过系统边界。入口若只能逐行写入、依赖额外磁盘,或绑定团队养不起的扩展,再快的查询引擎也难以发挥。

它还说明,“能运行”与“能长期维护”是两套标准。社区扩展率先证明方案可行,也给出了性能基线;纯 Java 的表函数方案则把速度、升级风险和团队技能放在一起权衡。工程上的关键改进,不是换了一个更响亮的数据库,而是让数据入口适应数据库的并行读取方式。

局限与未知

  • 所有结果来自同一篇用户客座文章,没有第二个独立信源交叉验证;文章也没有披露完整测试环境,速度数字不宜外推。
  • 公开样本比生产数据小得多,长文本投影仍会拖慢性能;材料没有说明这一问题最终是否解决。
  • 文章称纯 Java 管道追平社区扩展,但供稿未给出两者在真实数据上的完整计时、资源占用和长期稳定性数据。

供稿材料 SOURCES — 1

← 返回 2026-10-07 · 数据板块