alitrack

基于DuckDB的SQLFrame实现PySpark 一行不改,算力省 75%

SQLFrame:PySpark 一行不改,算力省 75%

2026年6月,阿姆斯特丹,DuckDB 的用户大会 DuckCon #7 上,默克(Merck KGaA)的数据平台负责人 Nicolas Renkamp 讲了一个企业迁移故事:这家 1668 年创立、62000 名员工的德国生命科学巨头,把跑了近十年的数千个 PySpark 转换作业迁到了 DuckDB 上,业务逻辑代码一行没改,每周计算量从 800 万秒降到 200 万秒,作业数反而从 500 涨到 600。

一句话总结这次迁移:换引擎,不换代码。

● ● ●

为什么要迁

默克 2017 年建成企业数据湖,主框架是 PySpark。到 2025 年,这些转换逻辑喂数百个数据产品、数千个用例,堆了近十年。三个痛点摆上桌面:祖传代码没人敢动、工程团队技能水平参差、新的单机计算引擎越看越眼馋(Renkamp 自称这种处境下的企业工程师为 enterprise pirate,企业海盗)。

下决心的依据是一组负载统计:在扫描量超过 1MB 的查询里,中位数查询只扫约 55.5MB,99.9 分位也只扫 35.23GB。这个口径化用自 Fivetran 2024 年对 Snowflake 和 Redshift 遥测数据的分析(行业中位数约 100MB、99.9 分位约 300GB),默克对自家负载做了同样的测算,结论比行业均值更极端:根本不需要分布式引擎。

● ● ●

怎么迁:换引擎不换代码

迁移的关键工具是开源项目 SQLFrame。它实现了完整的 PySpark DataFrame API,底层用 SQLGlot 把代码转译成目标引擎的 SQL,直接跑在 DuckDB 上,全程不依赖 Spark 集群和 Spark 库。

用的时候只需在脚本入口加两行:

from sqlframe import activate
activate(engine="duckdb")

之后代码里的 from pyspark.sql import SparkSession 一行不用改,实际拿到的是 SQLFrame 的 DuckDBSession,所有计算都落在 DuckDB。原理说穿了不神秘:它把 sys.modules 里的 pyspark 条目替换成自己的模块,再注入 DuckDBSession 改名为 SparkSession 这类别名。代价是 activate 必须在所有 pyspark import 之前执行,同一个进程里也没法多引擎来回切。

默克没有全量搬迁,而是选了两类目标:每天跑成百上千次、覆盖数千张表的高度标准化转换(典型如 SAP 数据清洗);以及那些输入输出看起来不大、Spark 却跑得七小时八小时的贵作业。

架构上保持五层里只动两层:计算引擎从 Spark 换成 DuckDB,逻辑层经 SQLFrame 平滑过渡,底下的计算基础设施、开放表格式、对象存储全部不动。基础设施从集群简化为带 NVMe SSD 的单机 EC2 实例,配置好溢写磁盘就能干活。

分工也清楚:平台团队负责设临时目录指向正确的 SSD、调性能参数(比如关闭插入顺序保证)、打通 S3 读取,再把生成的 SQL 管道进 COPY 语句统一执行;数据工程师照旧写原来的代码,对引擎切换无感。Renkamp 补了一句:真要做得稳,表格式应该上 DuckLake 或 Iceberg,拿内建的故障安全。

● ● ●

结果:作业更多,算力更省

第一个焦点区是 SAP 标准化转换。迁移完成后,每周计算量从约 800 万秒降到约 200 万秒,省了约 75%;同期作业数从约 500 涨到约 600。用更少的机器干更多的活,这是最硬的生产数字。

第二个焦点区是一个真实的大作业:18 个 UNION ALL、5 个 LEFT JOIN,转译出来的 SQL 有 11500 行。迁移前调度器跑一次要 3 到 7 小时 49 分(5 次真实运行记录),迁移后稳定在 10 到 23 分钟,折算加速 12 到 42 倍,且合并整个集群的 CPU 和内存看,资源占用大幅下降。

Renkamp 对为什么快的归因很直白:DuckDB 更擅长向量化执行,没有分布开销,里面装着十年的数据库研究成果。

支撑迁移推进的还有个心理因素。他描述那些祖传代码:活了九年、五个人碰过、四个已离职,里面全是当年为了逆转糟糕 ERP 决策打的补丁。拿着这种代码,用 SQLFrame 跑一遍、拿到 SQL、快了十倍,这个多巴胺瞬间让整个团队愿意继续迁下去。

● ● ●

为什么不用 LLM 转换

演讲的备用页有个梗图:两个按钮,一个是 SQLFrame,一个是问 LLM 一千万次,配图是满头大汗纠结的人。生态现状佐证了这个调侃:全网找不到星标过百的产品级 LLM 迁移工具,散落的个人项目都在个位数星标。零散地让 LLM 逐段转换,等于把九年补丁逻辑的语义正确性交给概率。

● ● ●

这套依赖链的真实结构

SQLFrame 看起来是个 535 星的单人项目(作者 Ryan Eakman),但往深处看:它构建在 SQLGlot 之上,SQLGlot 月下载量 7100 万次,是 SQL 转译领域的事实标准。2025 年 9 月 3 日,Fivetran 收购了 SQLGlot 和 SQLMesh 背后的 Tobiko Data,Eakman 本人也是 Fivetran 员工。整条链,从兼容层到转译引擎到知识产权,单点收敛于一家商业公司。

风险性质因此变了:不是个人弃坑,是厂商锁定。采用前值得掂量。另有两条工程纪律要注意:SQLFrame 对 DuckDB 没有内存安全阀,溢写目录和内存上限要在建连接时自己设(默克平台团队干的正是这个);SQLFrame 与 SQLGlot 必须成对升级,当前版本约束落后上游约 11 周。

● ● ●

官方也在做,赛道在赛跑

DuckDB 官方仓库里有个实验性的 Spark API(duckdb.experimental.spark),同样走同一份代码直跑 DuckDB 的路线,官方文档自标实验性、功能尚缺。它与 SQLFrame 构成官方和第三方的赛跑:SQLFrame 的优势是支持八种引擎(DuckDB 之外还有 BigQuery、Postgres、Snowflake 等,留了逃生舱)和更成熟的 API 覆盖。对企业采用者,这个赛局本身就是好消息:入口层的竞争才刚开始,价格是零,赌注是迁移信心。

● ● ●

值得借鉴的三件事

一、迁移催化剂是入口不是引擎。让默克下决心的是九年代码零改动这个前提,DuckDB 的性能只是兑现。任何想承接存量工作流的工具,先解决零改动进门,再谈引擎优势。

二、平台层兜底是隐形门槛。SQLFrame 不设内存上限、不配溢写目录,默克平台团队把这些活全接了过去。兼容层的零改码体验,是平台工程用配置换来的。

三、生成的 SQL 本身是资产。平台统一拦截并执行所有转译后的 SQL,意味着天然拥有全量 SQL 谱系,配上列级血缘能力就是企业治理最想要的东西。这是 Merck 模式里没被点破、商业价值可能最高的副产品。

默克把这次迁移定位为走向更自主数据栈的第一步,下一步看向 DuckLake。对企业海盗们,Renkamp 的结语是:take the DuckDB pill。

参考来源

https://blobs.duckdb.org/events/duckcon7/nicolas-renkamp-sqlframe-migrates-pyspark-to-duckdb.pdf

https://duckdb.org/events/2026/06/24/duckcon7/

https://github.com/eakmanrq/sqlframe

https://sqlframe.readthedocs.io/en/stable/duckdb/

https://www.fivetran.com/press/fivetran-acquires-tobiko-data-to-power-the-next-generation-of-advanced-ai-ready-data-transformation

https://www.fivetran.com/blog/how-do-people-use-snowflake-and-redshift

https://duckdb.org/docs/current/clients/python/spark_api