若要将外部或 foreign Delta Lake 表转换为 Azure Databricks 中的 Unity Catalog 托管表,请使用 ALTER TABLE ... SET MANAGED 命令;对于外部表,也可以使用 Catalog Explorer。 转换会保留表配置,包括名称、设置、权限和视图,并保留表历史记录。
对于外部表的转换,另请参阅:SET MANAGED
- 最大程度地减少读取器和编写器停机时间。
- 在转换过程中有效处理并发写入操作。
- 允许您将转换后的托管表回退为外部表。
- 重定向基于路径的读取和写入,以允许旧代码在转换后正常运行。
尽管也可以使用 CREATE TABLE AS SELECT(CTAS)将外部表转换,但 Databricks 建议使用 SET MANAGED,因为它具有这些优势。
对于外部表转换,Databricks 会将已转换表的预测优化设置为 INHERIT,而不是自动启用该功能。 请参阅 使用 SQL 的外部表。
若要将 foreign 表转换为外部 Unity Catalog 表,请参阅 将 foreign 表转换为外部 Unity Catalog 表。
Prerequisites
外部表
将外部表转换为托管表具有以下先决条件:
- 格式:表必须使用 Delta Lake 格式。
-
运行时:必须使用 Databricks Runtime 17.3 LTS 或更高版本或无服务器计算才能使用
SET MANAGED,UNSET MANAGED或者TRUNCATE UNIFORM HISTORY。 - 读取器和编写器:Azure Databricks源表的读取器和编写器必须使用 Databricks Runtime 15.4 LTS 或更高版本。 如果您的读取器或写入器使用 14.3 LTS 及以下版本,请参阅 旧版读取器和写入器。
-
外部客户端:外部(非 Databricks)客户端必须支持读取 Unity Catalog 托管表。 请参阅 使用 Delta 客户端访问表。
- 使用 Access Insights 仪表板查看访问表的读取程序和写入程序是 Databricks Runtime 还是外部非 Databricks 系统。
-
功能兼容性:如果您的表包含
minReaderVersion=2、minWriterVersion=7和tableFeatures={..., columnMapping},则SET MANAGED命令会失败,并报出DELTA_TRUNCATED_TRANSACTION_LOG错误。 使用DESCRIBE DETAIL验证您的表格是否具有这些属性。 请参阅 Delta Lake 功能兼容性和协议。
转换后,基于路径的读写操作会自动重定向到新的托管位置,性能上有轻微的影响。 Databricks 建议将所有基于路径的访问迁移到基于名称的访问,以避免性能开销。 请参阅 基于路径的重定向。
Important
若要避免冲突,请取消在外部表上运行的任何现有 OPTIMIZE 命令作业(液体聚类分析、压缩 ZORDER),并且不要在将外部表转换为托管表时计划任何作业。
外表
Important
将外部表转换为托管表功能现处于 公开预览 阶段。
将外部表转换为托管表需要满足以下前提条件:
- 数据格式:外部表必须使用 Delta Lake 格式。 若要为 Parquet 执行一次性转换,请参阅 “转换为 Delta Lake”。
- 运行时:Databricks Runtime 17.3 或更高版本。
- 表类型:Hive 元存储(HMS)表类型必须是外部 HMS 表。 如果表是托管 HMS 表,该命令将失败。
-
权限:对表具有
OWNER或MANAGE权限,并对EXTERNAL LOCATION具有CREATE权限。
停机时间和数据复制时间
与替代方法(如SET MANAGED)相比,该DEEP CLONE命令可最大程度地减少或消除停机时间。
外部表
外部表的转换过程采用两步法:
- 初始数据复制(无停机时间): 该命令将表数据和 Delta 事务日志从外部位置复制到托管位置。 对外部表进行读写的活动读取器和写入器可不中断地运行。
- 切换到托管位置(短暂停机): 在第一步中提交到外部位置的提交记录将被移动到托管位置,并更新表元数据以登记新的托管位置。 在此步骤中,会暂时阻止对外部位置的所有写入,从而导致编写器停机。 Databricks Runtime 16.4 LTS 或更高版本的读取器不会停机,但 Databricks Runtime 15.4 LTS 及更低版本的读取器可能会遇到停机的情况。
下表根据源表大小以及估计吞吐率(0.5–2 GB/CPU 核心/分钟)显示预计停机时间:
| 表大小 | 建议的群集大小 | 估计数据复制时间 | 估计的读取器和编写器停机时间 |
|---|---|---|---|
| 100 GB 或更少 | 32 核/超大型 SQL 仓库 | 约 6 分钟或更少 | 约 1-2 分钟或更少 |
| 1 TB(兆字节) | 64 核/2X 大型 SQL 仓库 | 约 30 分钟 | 约 1-2 分钟 |
| 10 兆字节 | 256 核/4X 大型 SQL 仓库 | ~1.5 小时 | 约 1-5 分钟 |
注释
停机时间可能因文件大小、文件数和提交次数等因素而异。
外部表
外部表转换的停机时间取决于您使用的是 MOVE 还是 COPY:
- 对于
MOVE,可能会发生停机,如外部表所述。 请参阅 外部表。 - 因此
COPY,你负责管理停机时间,因为转换过程会将源表复制到托管存储位置,从而创建两个单独的数据副本。 你负责禁用对外部目录中源表的读取和写入,以及迁移工作负载以使用新的托管表。
转换为托管表
使用目录资源管理器或 SQL 转换外部表,或使用 SQL 转换外部表。
使用目录资源管理器的外部表 (Beta)
Important
使用 Catalog Explorer 将外部表转换为托管表功能目前处于 Beta 阶段。
使用目录资源管理器,可以一次转换架构中的一个或多个外部表。
转到要在目录资源管理器中转换的表或架构。
在“ 关于此表 ”(表详细信息页)或“ 关于此架构 ”(架构详细信息页)下,单击“ 浏览优化”。
在“ 为何迁移到 Unity 目录托管表?” 对话框中,单击“ 继续”。
选择要转换的外部表。 如果从表详细信息页打开了对话框,目录资源管理器会预先选择表。 使用搜索栏查找其他表。 管理表无法被选择。
单击“ 创建转换笔记本”。
(可选)输入笔记本的名称。 默认情况下,这会将笔记本保存到主文件夹。 单击“ 浏览 ”将其保存到其他位置。
在笔记本中,查看最佳做法,并验证是否满足所有 先决条件。
SET运行 MANAGED Queries 单元格。
单元运行后,表类型在目录资源管理器中显示为 MANAGED 而不是 EXTERNAL 。 如果状态未立即更新,请刷新页面。
使用 SQL 的外部表
根据您的外部表是否启用了 Apache Iceberg 读取功能(UniForm),请选择运行以下命令之一。 若要验证表是否启用了 Iceberg 读取,请参阅 “验证 Iceberg 读取是否已启用”。
对于未启用 Iceberg 读取功能的 Unity Catalog 外部表,请运行以下命令:
ALTER TABLE catalog.schema.my_external_table SET MANAGED;转换后,可以在托管表上启用 Iceberg 读取,而无需兼容性问题。
对于已启用 Iceberg 读取功能的 Unity Catalog 外部表,请运行以下命令:
ALTER TABLE catalog.schema.my_external_table SET MANAGED TRUNCATE UNIFORM HISTORY;包括
TRUNCATE UNIFORM HISTORY以保持最佳表性能和兼容性。TRUNCATE UNIFORM HISTORY仅截断 UniForm Iceberg 历史记录,不会删除 Delta 历史记录。 此命令导致 Iceberg 截短后,出现短暂的读写停机时间。
表转换后,现有读取和写入流将失败。 重新启动具有相同配置的流,以自动使用基于路径的重定向。 验证读取器和写入器是否与托管表一起工作。 请参阅 流式处理行为。
除非手动关闭预测优化,否则转换后会自动启用预测优化。 请参阅 “验证是否启用了预测优化”。
Azure Databricks将 Unity 目录外部位置中的数据保留 14 天,以允许回滚。 请参阅 回滚托管表转换操作。 14 天后,启用预测优化后,Azure Databricks会自动删除此数据以回收存储并节省成本。 如果关闭预测优化,请在 VACUUM 14 天后在新转换的托管表上运行(需要 Databricks Runtime 17.3 LTS 或更高版本或无服务器计算),以自行回收存储。
VACUUM my_converted_table
注释
即使启用了预测优化,Unity Catalog 外部位置中的数据在 14 天后也可能不会被删除。 例如,当托管表不常使用或较小时,可能会发生这种情况。 如果以前的数据仍然存在,请手动运行 VACUUM 以将其删除。
Azure Databricks 仅删除外部位置中的数据。 将保留 Delta 事务日志以及对 Unity Catalog 中表的引用。
使用 SQL 的外部表
Important
将外部表转换为托管表功能现处于 公开预览 阶段。
若要将 Unity Catalog 外部表转换为 Unity Catalog 托管表,请运行以下命令:
ALTER TABLE source_table SET MANAGED {MOVE | COPY}
source_table
Unity Catalog 中已联邦化的现有外部表。
MOVE将表格转换为托管表,并在外部目录中禁用对该源表的访问。
将表转换后,通过外部目录或基于路径的访问会失败。 表的所有读取者和编写器都必须使用 Unity 目录命名空间进行访问。 例如:
SELECT * FROM catalog_name.schema_name.table_name;不支持基于路径的访问,转换表后失败。 例如:
SELECT * FROM delta.`protocol://path/to/table`;除非你手动进行了配置,否则预测优化将设置为
INHERIT。 若要检查是否启用了预测优化,请参阅 验证是否启用了预测优化。
COPY将表转换为托管表,而无需修改或禁用对外部目录中源表的访问。
- 在转换为托管表的过程中,转换过程会将数据从源表复制到为外部表定义的托管存储位置,从而生成两个独立的副本:新的托管表,以及外部目录中的源表。
- 与读取和写入失败的情况不同
MOVE,使用COPY时,你负责正确禁用对外部目录中源表的读取和写入,并确保工作负荷已迁移到新目录。
完成表转换后,您必须重启所有使用外部表的流式处理作业(读取或写入),并验证读取端和写入端能够与托管表正常工作。
在转换之前,如果在外部编目中删除源表,Unity Catalog 也会删除外部表。 将表转换为托管表后,删除外部目录中的源表不会影响 Unity 目录托管表。
如果在复制数据时命令中断,请重启它。 该命令会从上次中断处继续执行。
警告
Databricks 建议避免在同一个表上并发运行多个 SET MANAGED 命令,这可能会导致表状态不一致。
验证转换
若要验证表是否已成功转换为托管表,请检查该表 Type 是否为 MANAGED。 可以执行以下操作之一:
打开一个新选项卡,然后转到目录资源管理器。 在“ 详细信息 ”选项卡的“ 关于此表”下,表 类型 显示为 “托管”。
通过运行以下 SQL 命令检查表
Type:DESCRIBE EXTENDED catalog_name.schema_name.table_name若要一次性检查多个表或编写检查脚本,请改为查询
information_schema.tables:SELECT table_type FROM system.information_schema.tables WHERE table_catalog = 'catalog_name' AND table_schema = 'schema_name' AND table_name = 'table_name';
旧版读者和编写者
Databricks 建议将所有读取器和编写器升级到 Databricks Runtime 15.4 LTS 或更高版本,以使用完整功能 SET MANAGED,包括表历史记录保留。
如果你有使用 Databricks Runtime 15.3 或更低版本的读取器或写入器,仍然可以使用 SET MANAGED。 但是,转换为托管表后,只能按版本而不能按时间戳对历史提交版本执行时间回溯。
如果在 14 天内回滚为外部表,则会重新启用对转换前所做历史提交的时间旅行功能。 对于在转换与回滚之间对转换后的托管表所做的提交,不支持使用时间戳进行时间回溯。 请参阅 回滚托管表转换操作。
使用 Databricks Runtime 15.3 或更低版本在完成转换后写入表时,需要移除 inCommitTimestamp 功能:
ALTER TABLE <table_name> DROP FEATURE inCommitTimestamp;
基于路径的重定向
在 Databricks Runtime 18.1 及更高版本中,将外部表转换为 Unity 目录托管表后,基于路径的读取和写入操作会自动重定向到新的托管位置。 按路径读取是指诸如 SELECT * FROM delta.`/path/to/my_table 这样的代码。 基于路径的重定向可减少迁移到托管表所需的时间和工作量,方法是允许使用存储路径的旧代码在不重构的情况下继续工作。
外部表转换不会将基于路径的访问重定向。
对于低延迟用例,Azure Databricks建议将基于路径的访问迁移到基于名称的访问。 基于路径的重定向会为每次读取或写入操作增加数百毫秒的延迟,并要求旧的 Delta 日志保持在 Unity Catalog 的外部位置处于活动状态。 基于名称的读取和写入没有额外的性能开销。 请参阅 将基于路径的代码迁移为基于名称的代码。
将基于路径的代码迁移到基于名称的代码
如果决定不使用基于路径的重定向,则可以迁移旧代码。 若要迁移,请将基于路径的引用替换为基于名称的引用。
下面的代码示例包含对文件的基于路径的表引用:
SELECT * FROM delta.`/path/to/customers_table`;
将基于路径的引用替换为对外部表的基于名称的引用,如以下代码所示:
SELECT * FROM catalog_name.schema_name.customers_table;
流处理行为
使用基于路径的重定向进行流式处理支持以下 Databricks Runtime 版本中的读取和写入:
- Databricks Runtime 18.1 及更高版本中支持读取。
- Databricks Runtime 18.2 及更高版本中支持写入。
转换后,您必须重新启动所有流媒体任务,以避免从先前的表位置读取或写入数据。
基于路径的流式读取和写入操作发生故障,并在下一个检查点停止,且显示迁移消息:
- 在读取时,流将抛出错误:
DELTA_STREAMING_INTERRUPTED_BY_MANAGED_TABLE_CONVERSION: The table at <path> has been converted to a Unity Catalog managed table. The stream has been stopped to ensure data consistency. Restart the stream and it will automatically resume from the last committed offset using the converted table。 - 对于写入,转换后的第一个微批处理引发错误:
Operation not allowed: STREAMING WRITE cannot be performed on a table with redirect feature. The no redirect rules are not satisfied []
若要解决错误,请重新启动具有相同配置的流。 基于路径的访问会自动重定向到托管表。
有关基于路径的重定向限制,请参阅 “限制”。
排除转换失败
本部分介绍如何解决使用 SET MANAGED外部表转换为 Unity 目录托管表时的常见问题。
VERSIONED_CLONE_INTERNAL_ERROR.EXISTING_FILE_VALIDATION_FAILED
如果转换失败,请始终使用相同的 Databricks Runtime 版本重试。 可以在不同版本之间以不同的方式序列化元数据,如果在不同的 Databricks Runtime 版本上重试转换,则会导致 VERSIONED_CLONE_INTERNAL_ERROR.EXISTING_FILE_VALIDATION_FAILED 失败。
在转换期间关闭群集
如果在转换期间群集关闭,DELTA_ALTER_TABLE_SET_MANAGED_INTERNAL_ERROR 命令可能会失败。 重试该命令以恢复转换。
损坏的外部表
如果外部表已损坏(例如,无效表状态),则转换可能会失败,并出现错误,例如 DELTA_TRUNCATED_TRANSACTION_LOG, DELTA_TXN_LOG_FAILED_INTEGRITY或 DELTA_STATE_RECOVER_ERRORS。 在尝试转换之前,请验证是否可以对外部表运行基本操作,例如 DESCRIBE DETAIL。
文件验证失败
该 SET MANAGED 命令验证它是否已将表的最新快照中的所有文件复制到新的托管表位置。 如果缺少任何文件,命令将失败并显示 DELTA_ALTER_TABLE_SET_MANAGED_FAILED.FILE_VALIDATION_FAILED 错误。
若要解决此问题,请执行下列操作:
- 检查 Spark 驱动程序日志,以确定哪些文件无法迁移。
- 验证这些文件是否存在于源外部表位置并且可访问。
-
ALTER TABLE ... SET MANAGED重试命令。
如果问题仍然存在,请联系 Databricks 支持部门。
回滚托管表转换操作
Important
回滚命令需要无服务器计算或 Databricks Runtime 17.3 LTS 或更高版本。
外部表
将外部表转换为托管表后,可以在 14 天内使用 UNSET MANAGED 命令回滚。 这会更新表元数据,使其重新指向原始的外部位置。 Databricks 保留转换后对托管位置所做的所有写入。
若要回滚到外部表,请运行以下命令:
ALTER TABLE catalog.schema.my_managed_table UNSET MANAGED;
请牢记以下信息:
- 如果回滚命令中断或失败,请重新运行以重试。
- 回滚后,您必须重启流式处理作业,这与转换时类似。
- 在转换与回滚之间这段时间内对托管位置所做的提交支持按版本进行时间回溯,但不支持按时间戳进行时间回溯。
- 回滚七天后,Azure Databricks 会自动删除托管位置中的数据。
外部表: MOVE
警告
必须在删除托管表之前运行 UNSET MANAGED 。 删除表而不首先运行 UNSET MANAGED 可能会导致数据丢失或不一致。
可以使用 UNSET MANAGED 命令回滚表迁移操作,并重新获得对外部目录中源表的访问权限。 回滚需要两个步骤:首先,必须将该表回滚为外部表;然后,删除该外部表,以将该表重新联合为外来表。
- 若要回滚到外部表,请运行以下命令:
ALTER TABLE catalog.schema.my_managed_table UNSET MANAGED
- 若要将该表重新联邦到外来表,请使用以下命令删除外部表:
DROP TABLE catalog.schema.my_managed_table
外部表将在下一次目录同步后可用。
请牢记以下信息:
- 对于在转换和回滚之间对外部位置进行的提交,可以按版本(而不是时间戳)进行时间传输。
- 回滚七天后,Databricks 将删除托管位置中的数据。
外部表: COPY
若要回滚表迁移,无需运行 UNSET MANAGED 命令,因为外部目录中的源表未修改。 删除该托管表后,Databricks 会在下一次目录同步后将其重新联邦化为外部表。
验证回滚
对外部表和外来表采用不同方式验证回滚。
外部表
若要验证托管表是否已成功回滚到外部表,请检查表 Type 是否为 EXTERNAL。 可以执行以下操作之一:
打开一个新选项卡,然后转到目录资源管理器。 在“ 详细信息 ”选项卡的“ 关于此表”下,表 类型 显示为 “外部”。
通过运行以下 SQL 命令检查表
Type:DESCRIBE EXTENDED catalog_name.schema_name.table_name若要一次性检查多个表或编写检查脚本,请改为查询
information_schema.tables:SELECT table_type FROM system.information_schema.tables WHERE table_catalog = 'catalog_name' AND table_schema = 'schema_name' AND table_name = 'table_name';
外表
若要验证托管表是否已成功回滚为外部表,请检查表 Type 是否为 FOREIGN。 可以执行以下操作之一:
打开一个新选项卡,然后转到目录资源管理器。 在“ 详细信息 ”选项卡的“ 关于此表”下,表 类型 显示为 “外部”。
通过运行以下 SQL 命令检查表类型:
SELECT table_type FROM system.information_schema.tables WHERE table_catalog = 'catalog_name' AND table_schema = 'schema_name' AND table_name = 'table_name';列
table_type显示为FOREIGN.
注释
请勿使用 DESCRIBE EXTENDED 来验证外部表转换或回滚。 Federation 对此命令使用 hive_metastore 目录行为,因此无论该表的实际状态如何,都会将表 Type 显示为 EXTERNAL。
高级主题
本部分包含用于将外部表和外部表转换为托管表的高级主题。
在架构或目录级别转换
可以使用以下两个选项在架构或目录级别自动转换表:
遍历各个架构中的表,逐个转换每个表。
使用 discoverx 实验室项目一次性转换整个架构或目录:
df = (dx.from_tables("prod.*.*") .with_sql("ALTER TABLE {full_table_name} SET MANAGED;") .apply())
请参阅 Databricks Labs 和 discoverx。
在外部目录中创建表
您可以在 foreign catalog 中创建外部表或托管表。 行为取决于架构配置:
-
对于 Glue 或 eHMS 架构,或者 对于 Unity 目录中设置了托管位置的架构:如果运行
CREATE TABLE foreign_catalog.schema.table,这将创建 Unity 目录托管表或外部表。 Databricks 不会将表推送或同步到外部目录。 -
对于来自内部 Hive 元存储连接的模式:如果尝试在外部模式中创建表,它仍然会创建一个外表,并在 Hive 内部架构
hive_metastore创建一个表。 - 对于旧版工作区 Hive 元存储:由于其支持读写联邦,如果您在外部目录中创建表,系统也会在内部 Hive 元存储中创建一个表。
基于 DBFS 的外部表
转换 DBFS 支持的表时,Databricks 会将 DBFS 路径的当前映射存储为外部表的云路径位置。
限制
将外部表或外来表转换为托管表有以下限制:
对于在转换之后但在回滚之前所做的提交,表历史记录支持按版本进行时间旅行,但不支持按时间戳进行时间旅行。
OpenSharing 与
SET MANAGED命令不完全兼容。 支持 Open OpenSharing,但 Databricks 到 Databricks 的共享不会自动更新接收方表的托管位置。 接收者会继续从旧位置读取数据,直到您重新共享该表。 若要重新共享表,请运行以下命令:ALTER SHARE <share_name> REMOVE TABLE <table_name>; ALTER SHARE <share_name> ADD TABLE <table_name> AS <table_share_name> WITH HISTORY;如果 Unity 目录元存储、目录或架构的默认托管位置与源表的存储位置位于不同的云区域中,则可能会从云提供商产生额外的跨区域数据传输成本。
若要验证架构和目录的位置,请运行以下命令:
DESC SCHEMA EXTENDED <catalog_name>.<schema_name>; DESC CATALOG EXTENDED <catalog_name>;若要验证元存储的位置,请运行以下命令之一:
DESC METASTORE; -- Option 1 SELECT * FROM system.information_schema.metastores; -- Option 2
基于路径的重定向限制:
- 转换后,必须重启任何流式处理作业。 请参阅 流式处理行为。
- 基于路径的重定向仅对迁移过程具有向后兼容性,并且不启用对 Unity 目录托管表的新基于路径的访问。
外部表限制:
- 仅支持转换通过 Hive 元存储和 Glue Federation 进行联合查询的外部表。