使用 Delta Lake 列映射重命名和删除列

Delta Lake 列映射支持仅通过更改元数据来重命名或删除列,而无需重写数据文件。 列映射还允许 Parquet 在列名(如空格)中不支持的字符,因此无需重命名列即可将 CSV 或 JSON 数据直接引入 Delta Lake。

先决条件

在启用列映射之前,请查看 “限制”。

列映射需要满足以下条件:

  • Delta 协议:读取器版本 2 或更高版本,以及写入器版本 5 或更高版本。 请参阅 Delta Lake 功能兼容性和协议
  • 读取启用了列映射的表需要 Databricks Runtime 10.4 LTS 及更高版本

启用列映射

使用以下命令在新表上启用模式id的列映射:

CREATE table <table-name> (
  id INT,
  name STRING
)
USING DELTA
TBLPROPERTIES (
  'delta.columnMapping.mode' = 'id'
);

使用以下命令在现有表上启用name模式的列映射:

ALTER TABLE <table-name> SET TBLPROPERTIES (
  'delta.columnMapping.mode' = 'name'
)

有关列映射模式的详细信息,请参阅 列映射模式

重命名列

为 Delta Lake 表启用列映射后,可以重命名列:

ALTER TABLE <table-name> RENAME COLUMN old_col_name TO new_col_name

有关更多示例,请参阅 更新具有架构演变的表架构

删除列

为 Delta Lake 表启用列映射后,可以删除一个或多个列:

ALTER TABLE table_name DROP COLUMN col_name
ALTER TABLE table_name DROP COLUMNS (col_name_1, col_name_2, ...)

有关详细信息,请参阅 更新具有架构演变的表架构

列映射模式

delta.columnMapping.mode 属性允许仅元数据更改将列标记为已删除或重命名,而无需重写数据文件。 以下模式可用:

  • none (默认值):未启用列映射。 列名需遵循 Parquet 命名约束。
  • name:启用此功能后,可执行仅限于元数据的列重命名和删除操作,并允许在列名中使用特殊字符。 name 可以在新的和现有的表中设置模式。
  • id:启用此功能后,可执行仅限于元数据的列重命名和删除操作,并允许在列名中使用特殊字符。 id 模式必须在创建表时设置,不能在现有表上设置。

注释

Databricks 建议在大多数用例中使用 id 模式以确保兼容性。 但是,如果未为提供值,并且启用了例如UniForm之类的Iceberg兼容功能,则会自动设置模式。

列名中支持的字符

为 Delta Lake 表启用列映射后,可以在列名中包含空格和其中任何字符: ,;{}()\n\t=

删除列映射

Warning

删除列映射会重写所有数据文件,以将物理列名替换为逻辑名称。 此操作不支持行级或物理冲突解决机制。

并发写入操作将导致 ConcurrentModificationException

删除列映射之前:

  1. 暂停所有并发写入操作,包括流式处理作业和ETL管道。
  2. 关闭表上的 预测优化
  3. 对于大型表,将此操作计划在低活动期间执行。

可以使用以下命令从表中删除列映射:

ALTER TABLE <table-name> SET TBLPROPERTIES ('delta.columnMapping.mode' = 'none')

若要删除列映射并降级表协议,请参阅 “维护兼容性”。

保持兼容性

在 Databricks Runtime 15.4 LTS 及更高版本中,可以使用 DROP FEATURE 该命令删除列映射并降级表协议,从而与使用 Databricks Runtime 10.3 及更低版本的读取器保持兼容性。

重要

从表中删除列映射不会删除分区表的目录名称中使用的随机前缀。

请参阅删除 Delta Lake 表功能并降级表协议

列映射和流式处理

非累加架构更改(如列重命名或删除)可能会中断流式读取。 使用 a schemaTrackingLocation 允许 Delta Lake 跟踪架构更改并防止流故障。

Configuration

配置 schemaTrackingLocation时:

  • 从源表读取的每个流式传输都必须具有自己的 schemaTrackingLocation
  • schemaTrackingLocation 必须位于流式写入目标的 checkpointLocation 目录中。
  • 对于从多个源表读取的工作负荷,请为每个源指定唯一的子目录 checkpointLocation

有关流式传输 Delta Lake 选项的完整列表,请参阅 Delta Lake

在活动流上启用列映射

若要在活动流式处理作业上启用列映射,请执行以下操作:

  1. 停止流传输
  2. 启用表上的列映射
  3. 重启流(首次重启时会初始化列映射)
  4. 再次重启流(第二次重启 - 启用架构更改)

任何进一步的架构更改(添加或删除列或更改列类型)都需要重启流。

若要为从含列映射的 Delta Lake 表读取的流式传输指定 schemaTrackingLocation,请使用以下示例:

checkpoint_path = "/path/to/checkpointLocation"

(spark.readStream
  .option("schemaTrackingLocation", checkpoint_path)
  .table("delta_source_table")
  .writeStream
  .option("checkpointLocation", checkpoint_path)
  .toTable("output_table")
)

局限性

启用列映射可能会导致以下功能失效:

  • 利用目录名称来读取 Delta Lake 表的旧式工作负荷。 具有列映射的分区表使用随机前缀,而不是分区目录的列名。 请参阅 Delta Lake 和 Parquet 分区兼容性
  • 使用更改数据源的下游操作。 请参阅 具有列映射的表
  • 流式传输从 Delta Lake 表读取,包括在 Lakeflow Spark 声明式管道中的流式传输。 请参阅 列映射和流式处理

其他资源