热点Databricks新闻
破除SQL迁移迷思:新SQL功能让向湖仓的“直接迁移”更简单
Databricks 展示了如何将传统数据仓库中的存储过程、游标、临时表和事务逻辑直接翻译为 Databricks SQL 脚本,无需重写为 Python 或 Spark。新功能如原生游标支持、BEGIN ATOMIC 事务和 Unity Catalog 治理,使迁移时间缩短 50-75%,并保留原有业务逻辑,让 SQL 团队继续维护。
标题:破除SQL迁移迷思:新SQL特性如何让平迁至Lakehouse变得更简单
正文: - 游标驻留在那个每晚定时运行的存储过程中。那张没人写文档的临时表。那个将三次更新捆绑在一起、任一失败即回滚的事务。所有这些,现在都能逐行迁移。 - 你翻译这个过程,而不是重写它。PL/SQL逐段映射到Databricks SQL Scripting,相同的业务逻辑,相同的控制流,相同的SQL团队。 - 这个过程最终进入Unity Catalog,带有血缘关系与访问控制。这是原有schema从未有过的治理能力。
在你数据仓库的某个角落,成百上千的存储过程每晚悄然唤醒,默默维持着业务的运转。它们是多年前由一批早已离职的SQL开发者编写的。它们有嵌套游标。它们动态创建临时表。它们将跨多张表的更新捆绑到单个事务中。而在第47行附近,有一条注释简单地写着:“不要更改此段。”如今没有人能完全理解这些存储过程了。然而每个人都依赖它们。收入仪表盘、财务结算、运营报告——所有这些,都以某种方式追溯到这些过程化SQL业务逻辑层。
将数据迁移到Lakehouse已是众所周知的事情。真正的阻力在于任何数据仓库迁移的过程化核心:存储过程、事务处理、临时表、控制流,以及这样一个事实——企业很大程度上仍依赖SQL技能。每次提起迁移,这些存储过程就成了所有人首先指出的问题:“除非我们能以最小改动运行这些,否则无法迁移。我们的企业仍然重度依赖SQL。”
因此,我们决定选取一个你可能此刻正在思考的用例——一个我们在多次迁移中都见过的复合存储过程——并在Lakehouse上逐段演示它。这个示例基于Oracle迁移用例,但可以适用于任何数据仓库(无论是遗留系统还是云上系统)。
以原始业务逻辑为例
这个示例过程处理每日订单。它将未处理的订单暂存到临时表中,对照客户主数据进行验证,循环遍历失败记录并逐一记录每个拒绝原因,然后更新区域收入汇总并将所有订单标记为已处理,所有这些都在一个事务中完成,失败时回滚。
这是一个不可拆分的夜间任务。
过去,迁移这意味着用Python和Spark完全重写。数周的工作、需要排查的新bug,以及一个再也无法维护自己业务逻辑的SQL团队。
我们没有重写它。我们翻译了它。
现在在Databricks上打下基础
每个存储过程都以一个签名和一个安全网开始。遗留代码将主体包裹在BEGIN ... EXCEPTION ... END中。Databricks改用DECLARE EXIT HANDLER FOR SQLEXCEPTION;思路相同,语法略有差异。假设会话中已设置了相应的catalog和schema。
最大的区别不在代码本身,而在于部署之后发生的事情。在Databricks上,存储过程注册在Unity Catalog中。它获得访问控制、列级血缘关系,以及跨所有工作区的可发现性。而在现有系统中,它存在于一个只有三个人知道密码的schema里。
| 遗留系统 | Databricks | |
|---|---|---|
| CREATE OR REPLACE PROCEDURE name IS | CREATE OR REPLACE PROCEDURE [IF NOT EXISTS] . . ( [ procedure_parameter [, ...] ] ) [ characteristic [...] ]LANGUAGE SQL SQL SECURITY { INVOKER | DEFINER }AS BEGIN |
| v_id NUMBER; 在BEGIN之前 | DECLARE v_id INT; 在BEGIN内部 | |
| EXCEPTION WHEN OTHERS THEN | DECLARE EXIT HANDLER FOR SQLEXCEPTION |
参考:docs.databricks.com/aws/en/sql/language-manual/sql-ref-syntax-ddl-create-procedure
然后我们处理临时表:数据仓库迁移中的轻松胜利
原始过程创建了两张临时表,用于暂存和验证失败记录。它们是其余逻辑所依赖的临时工作空间。
在Databricks上,这成为迁移中最简单的部分之一。不需要EXECUTE IMMEDIATE。不需要ON COMMIT PRESERVE ROWS。会话级的CREATE TEMP TABLE是直接替代方案,只有一个小注意事项:CREATE OR REPLACE TEMP TABLE尚不支持,因此如果需要在同一会话中可重复运行,需要先执行drop。
参考:docs.databricks.com/aws/en/tables/temporary-tables
游标是难点——至少我们原本这么认为
这是所有人都认为需要重写的部分。原始过程逐条遍历验证失败记录,拒绝每个错误订单,并记录原因。经典游标模式。数十年的遗留系统(例如Oracle)肌肉记忆。
Databricks的SQL scripting自Runtime 18.1起原生支持游标,包括OPEN、FETCH和CLOSE。%NOTFOUND属性变为CONTINUE HANDLER FOR NOT FOUND。循环标签和LEAVE替代了EXIT WHEN。
脚本逻辑竟然毫无波澜。
条件检查——如果没有待处理的行,则跳过并记录日志——几乎未作改动。SELECT ... INTO 变为 SET var = (SELECT ...)。其余部分完全一致。
我们的 SQL 脚本支持完整的过程化工具集:IF/ELSE、WHILE、FOR、LOOP、REPEAT、LEAVE、ITERATE、SIGNAL/RESIGNAL。如果您的代码库中包含 Teradata BTEQ 脚本,其中的 .GOTO 和 .LABEL 指令可映射为使用 LEAVE 和 ITERATE 的带标签循环。
参考:docs.databricks.com/aws/en/sql/language-manual/sql-ref-scripting
事务——这一刻才真正落地
这是最后一块拼图,也是让迁移真正可行的那一步。原始过程更新 regional_revenue,将订单标记为已处理,并记录批次信息。如果任何部分失败,则全部回滚。
在传统系统上,这是一个隐式事务加显式 COMMIT。在 Databricks 上,BEGIN ATOMIC ... END 提供相同的语义——成功时自动提交,失败时自动回滚——并且有一个显著优势:行级冲突检测。并发批次写入同一张表时,只有触及相同行才会发生冲突。例如,Oracle 和 Snowflake 都使用表级锁定,这迫使事务串行执行。
MERGE 语句可以原样迁移到 Databricks。显式 COMMIT 消失了,因为 BEGIN ATOMIC 已代为处理。团队也不再担心并发批处理作业相互踩踏。
- 在原子块内定义的每个表都必须启用 catalogManaged 表特性。您可以就地启用现有 Delta 表上的该特性:ALTER TABLE SET TBLPROPERTIES('delta.feature.catalogManaged'= 'supported');
- BEGIN ATOMIC 必须位于顶层——在 SQL 脚本、笔记本单元格或 SQL 作业任务中。
参考:docs.databricks.com/aws/en/transactions/
完整的迁移后过程
相同的业务逻辑。相同的控制流。由 Unity Catalog 统一治理。
我们的经验总结
这些程序的迁移时间可缩短 50-75%,即使是依赖大量 PL/SQL 包的复杂存储过程也不例外。这种效率源于一种机械式的翻译过程,它保留了原始业务逻辑,确保 SQL 团队能够无缝地继续其维护工作。除了迁移本身,团队还获得了一个强大的新优势:一个统一平台,同一份受治理的数据同时驱动着他们的仪表板、机器学习模型和 AI 项目。
要了解您的存储过程能否成功转换,唯一的方法就是试一个。从批次中挑选最小的存储过程,最好是一个没人喜欢调试的。在工作区中创建迁移项目,立即开始使用 Agentic Code Convertor!
订阅获取最新文章
立即注册