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 模式以确保兼容性。 但是,如果未为
列名中支持的字符
为 Delta Lake 表启用列映射后,可以在列名中包含空格和其中任何字符: ,;{}()\n\t=
删除列映射
Warning
删除列映射会重写所有数据文件,以将物理列名替换为逻辑名称。 此操作不支持行级或物理冲突解决机制。
并发写入操作将导致 ConcurrentModificationException。
删除列映射之前:
- 暂停所有并发写入操作,包括流式处理作业和ETL管道。
- 关闭表上的 预测优化 。
- 对于大型表,将此操作计划在低活动期间执行。
可以使用以下命令从表中删除列映射:
ALTER TABLE <table-name> SET TBLPROPERTIES ('delta.columnMapping.mode' = 'none')
若要删除列映射并降级表协议,请参阅 “维护兼容性”。
保持兼容性
在 Databricks Runtime 15.4 LTS 及更高版本中,可以使用 DROP FEATURE 该命令删除列映射并降级表协议,从而与使用 Databricks Runtime 10.3 及更低版本的读取器保持兼容性。
重要
从表中删除列映射不会删除分区表的目录名称中使用的随机前缀。
列映射和流式处理
非累加架构更改(如列重命名或删除)可能会中断流式读取。 使用 a schemaTrackingLocation 允许 Delta Lake 跟踪架构更改并防止流故障。
Configuration
配置 schemaTrackingLocation时:
- 从源表读取的每个流式传输都必须具有自己的
schemaTrackingLocation。 -
schemaTrackingLocation必须位于流式写入目标的checkpointLocation目录中。 - 对于从多个源表读取的工作负荷,请为每个源指定唯一的子目录
checkpointLocation。
有关流式传输 Delta Lake 选项的完整列表,请参阅 Delta Lake。
在活动流上启用列映射
若要在活动流式处理作业上启用列映射,请执行以下操作:
- 停止流传输
- 启用表上的列映射
- 重启流(首次重启时会初始化列映射)
- 再次重启流(第二次重启 - 启用架构更改)
任何进一步的架构更改(添加或删除列或更改列类型)都需要重启流。
例
若要为从含列映射的 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 声明式管道中的流式传输。 请参阅 列映射和流式处理。