使用液态聚类对表进行分析

液体聚类分析是一种数据布局优化技术,用于替换表分区和 ZORDER。 它通过基于群集密钥自动组织数据,简化了表管理和优化查询性能。

与传统分区不同,可以重新定义聚类键,而且无需重写现有数据。 这样,数据布局就可以随着分析需求的变化而发展。 液态聚类适用于流式表和物化视图。

Important

在 Databricks Runtime 15.4 LTS 及以上版本中,Liquid 聚类功能已针对 Delta Lake 表正式发布;在 Databricks Runtime 16.4 LTS 及以上版本中,该功能对于 Apache Iceberg 表处于公开预览阶段。 Databricks 建议使用最新的 Databricks Runtime 来获得最佳性能。

托管 Apache Iceberg v3 表还支持删除向量、行跟踪、行级并发和自动液体聚类分析。 这些功能需要 Databricks Runtime 18.0 及更高版本。 请参阅 使用 Apache Iceberg v3 功能。

何时使用液体聚类分析

Databricks 建议对所有新表采用液态聚类,包括流式处理表和物化视图。 以下方案特别受益于群集:

  • 筛选高基数列的查询。
  • 数据严重偏斜的表。
  • 增长迅速的表格需要维护和优化工作。
  • 具有并发写入要求的表。
  • 访问模式多样或可变的表。
  • 典型的分区键可能会返回过多或太少分区的结果的表。

Tip

如果你的查询经常集中在某一列进行分组或筛选,比如查找每个类别的最新日期,请使用 带有分层聚类的优先聚类键来优先处理该列。 优先将高基数列作为聚类键,可能会降低其他聚类键的聚类有效性,因此在应用之前请先评估其中的权衡。

启用液体聚类分析

可以在现有未分区表上或在创建表期间启用液体聚类分析。 聚类分析与分区或 ZORDER 不兼容。 Databricks 建议允许平台管理您表格中数据的所有布局和优化操作。 启用液体聚类分析后,运行 OPTIMIZE 作业以增量方式对数据进行群集化。 请参阅如何触发聚类。

使用聚类分析创建表

若要启用液体聚类分析,请将 CLUSTER BY 短语添加到表创建语句,如以下示例所示。 在 Databricks Runtime 14.3 LTS 及更高版本中,可以使用 Python 或 Scala 中的数据帧 API 和 DeltaTable API 为 Delta Lake 表启用液体聚类分析。

SQL

若要创建带聚类的空表,请执行以下步骤:

CREATE TABLE table1 (col0 INT, col1 STRING) CLUSTER BY (col0);

若要使用聚类分析从现有数据创建表, CLUSTER BY 必须在表名称后面显示,而不是子句中 SELECT :

CREATE TABLE table2 CLUSTER BY (col0)
AS SELECT * FROM table1;

如需复制表结构(包括其聚类配置):

CREATE TABLE table3 LIKE table1;

Python

若要使用 API 创建具有聚类分析的 DeltaTable 空表,请执行以下操作:

(DeltaTable.create()
  .tableName("table1")
  .addColumn("col0", dataType = "INT")
  .addColumn("col1", dataType = "STRING")
  .clusterBy("col0")
  .execute())

从现有 DataFrame 创建表:

df = spark.read.table("table1")
df.write.clusterBy("col0").saveAsTable("table2")

若要使用 DataFrameWriterV2 API 创建表(在 Databricks Runtime 14.2 及更高版本中可用):

df = spark.read.table("table1")
df.writeTo("table1").using("delta").clusterBy("col0").create()

Scala

若要使用 API 创建具有聚类分析的 DeltaTable 空表,请执行以下操作:

DeltaTable.create()
  .tableName("table1")
  .addColumn("col0", dataType = "INT")
  .addColumn("col1", dataType = "STRING")
  .clusterBy("col0")
  .execute()

从现有 DataFrame 创建表:

val df = spark.read.table("table1")
df.write.clusterBy("col0").saveAsTable("table2")

若要使用 DataFrameWriterV2 API 创建表(在 Databricks Runtime 14.2 及更高版本中可用):

val df = spark.read.table("table1")
df.writeTo("table1").using("delta").clusterBy("col0").create()

Important

使用 DataFrame API 设置聚类键时,指定聚类列只能在创建表时或在使用 overwrite 模式(例如,CREATE OR REPLACE TABLE 操作)时进行。 使用 append 模式时,无法更改群集密钥。

若要在追加数据时更改现有表上的聚类分析键,请使用 SQL ALTER TABLE 命令与数据写入作分开修改聚类分析配置。 请参阅 “更改群集密钥”。

在 Databricks Runtime 16.4 LTS 及更高版本中,您可以使用 Structured Streaming 进行写入来创建已启用液态聚类的表,如以下示例所示:

SQL

CREATE TABLE table1 (
  col0 STRING,
  col1 DATE,
  col2 BIGINT
)
CLUSTER BY (col0, col1);

Python

(spark.readStream.table("source_table")
  .writeStream
  .clusterBy("column_name")
  .option("checkpointLocation", checkpointPath)
  .toTable("target_table")
)

Scala

spark.readStream.table("source_table")
  .writeStream
  .clusterBy("column_name")
  .option("checkpointLocation", checkpointPath)
  .toTable("target_table")

警告

启用了液体聚类分析的 Delta Lake 表使用 Delta 编写器版本 7 和读取器版本 3。 不支持这些协议的 Delta 客户端无法读取这些表。 不能降级表协议版本。 请参阅 Delta Lake 功能兼容性和协议。

若要替代默认功能启用(如删除向量),请参阅“替代默认功能启用”(可选)。

对现有表启用

若要在现有未分区的 Delta Lake 表上启用液体聚类分析,请执行以下操作:

ALTER TABLE <table_name>
CLUSTER BY (<clustering_columns>)

对于托管的 Apache Iceberg 表,请注意以下事项:

  • 对于具有 v2 规范的表,在现有表上启用液体聚类分析时,必须显式关闭删除向量和行跟踪。
  • 对于具有 v3 规范的表,不需要关闭这些功能,因为支持删除向量和行跟踪。 请参阅 使用 Apache Iceberg v3 功能。

注释

默认行为不对以前写入的数据应用聚类分析。 若要强制重新聚类,请使用 OPTIMIZE <table_name> FULL 或 OPTIMIZE <table_name> FULL WHERE <predicate>。 请参阅 强制重聚类化。

将分区表转换为液体聚类分析

在 Databricks Runtime 18.1 及更高版本中,若要将现有的已分区 Delta Lake 表转换为液态聚类,请在 REPLACE PARTITIONED BY WITH CLUSTER BY 语句中使用 ALTER TABLE。 转换可最大程度地减少读取器和编写器停机时间,并支持外部表和托管表。 转换后,表支持使用 Databricks Runtime 13.3 LTS 及更高版本的读取。

注释

对于托管 Iceberg 表,无需进行转换,因为这些表使用分区定义作为液态聚类键。 运行转换命令会引发错误。

将分区表转换为液体聚类分析的好处包括:

  • 针对数据跳过效果不佳或过度分区的表的性能改进。
  • 使用 CLUSTER BY AUTO 对查询模式频繁变化的表进行自动性能改进。
  • 聚簇列灵活且易于修改,而分区则较为固定,难以更改。
  • 由于具有液体聚类分析的表允许行级并发,因此减少了写入冲突。 请参阅 行级并发。

Syntax

ALTER TABLE <table_name>
REPLACE PARTITIONED BY WITH CLUSTER BY [( <clustering_columns> ) | AUTO]

该 CLUSTER BY 子句支持以下选项:

  • ( <clustering_columns> ):指定新的聚类列。 Databricks 建议使新的聚类列与原始分区列保持相似。 使用截然不同的列会在首次OPTIMIZE运行时触发一次大规模重新聚类操作。
  • AUTO:使用当前分区列作为初始聚类分析列,并允许预测优化随时间推移进行调整。 仅适用于 Unity Catalog 的托管表。 请参阅 自动液体聚类。
  • 未指定任何选项:使用当前分区列用作新的聚簇列。

有关从分区表迁移时选择群集键的指导,请参阅 从分区或 Z 顺序迁移。

示例

若要按与原始分区列不同的列进行聚簇,例如,对于按 (year, month, day) 分区的表,请执行以下操作:

ALTER TABLE t1 REPLACE PARTITIONED BY WITH CLUSTER BY (day, id);
OPTIMIZE t1;

注释

若要从更改聚类分析列中获益,必须运行 OPTIMIZE。

若要使用自动液体聚类分析并从当前分区列开始,请执行以下操作:

ALTER TABLE t2 REPLACE PARTITIONED BY WITH CLUSTER BY AUTO;

若要将当前分区列保留为聚类分析列,请执行以下操作:

ALTER TABLE t3 REPLACE PARTITIONED BY WITH CLUSTER BY;

在转换期间处理并发读取和写入

转换后,支持使用 Databricks Runtime 13.3 LTS 及更高版本进行读取和写入。 Azure Databricks建议在转换期间读取或写入表的工作负荷使用 Databricks Runtime 15.4 LTS 及更高版本。

请参阅下表,了解如何在转换期间处理并发读取和写入工作负荷:

工作负荷类型 转换期间读取 在转换期间写入
Batch 无停机时间。 所有 Databricks Runtime 版本都可以在转换期间读取表。 Databricks Runtime 15.4 及更高版本不会停机。
对于 Databricks Runtime 15.3 及更低版本,Databricks 建议在转换完成后暂停工作负荷,然后在转换完成后重启工作负荷。
Streaming 启用架构跟踪和列映射后:重启流而不丢失任何提交。
如果没有架构跟踪和列映射:流将引发异常。 使用新的检查点位置和起始版本重新启动。 提交不会丢失。
重启该流,且不会丢失任何提交。

验证或撤销转换

要验证转换是否成功,请运行 DESCRIBE EXTENDED 查看新的聚类列。 运行 DESCRIBE HISTORY 以查看一系列 REORG 操作、操作 UPGRADE PROTOCOL 和 REPLACE PARTITIONED BY WITH CLUSTER BY 操作。

要还原更改,可以用CTAS重新创建表格,或使用表格版本恢复表格。

用CTAS重建该表格

用CTAS重新创建表格,以保留转换后发生的数据更改。 这种方法会重写整个表,并不会保留所有表元数据。 要重建该表,可以使用 CREATE TABLE AS SELECT (CTAS) 语句:

ALTER TABLE my_table UNSET TBLPROPERTIES ('delta.liquid.hierarchicalClusteringColumns');
ALTER TABLE my_table CLUSTER BY NONE;
CREATE OR REPLACE TABLE my_table PARTITIONED BY (<partition_columns>) AS SELECT * FROM my_table;

恢复表

恢复该表,使其保留在转换为液态聚类之前的状态,并避免完全重写。 这种方法会丢弃恢复版本后所有数据和元数据的更改。 要恢复,请按照以下步骤操作:

  1. 使用 DESCRIBE HISTORY 标识要还原到的版本。

    DESCRIBE HISTORY my_table
    
  2. 请验证该版本可读且其数据文件未被删除:VACUUM

    SELECT * FROM my_table VERSION AS OF <version_before_conversion> LIMIT 10;
    
  3. 要恢复转换,请运行以下操作:

    ALTER TABLE my_table UNSET TBLPROPERTIES ('delta.liquid.hierarchicalClusteringColumns');
    ALTER TABLE my_table CLUSTER BY NONE;
    TRUNCATE TABLE my_table;
    RESTORE TABLE my_table TO VERSION AS OF <version_before_conversion>;
    

    警告

    该方法恢复完整的表状态,并丢弃所有后续更改,包括写入、模式变更、表属性和协议变更。 保留写入操作,并计划重新应用元数据更改。 在回滚前停止写入,并保持其停止状态,直到恢复完成。 在RESTORE之后立即运行TRUNCATE,以免被截断的文件被VACUUM删除。 下游流媒体工作负载在恢复后可能会表现不佳。

转换按时间戳列分区的表

若要转换按时间戳列()分区的表(t1timestamp_col)并使用时间戳列作为聚类键,必须设置其他配置:

SET spark.databricks.delta.liquidConversion.statsGeneration.enabled = false;
ALTER TABLE t1 REPLACE PARTITIONED BY WITH CLUSTER BY (timestamp_col, id);
ANALYZE TABLE t1 COMPUTE DELTA STATISTICS;

如果尝试在没有这些配置的情况下将时间戳分区列转换为聚类分析列,该命令将引发错误:

ALTER TABLE REPLACE PARTITIONED BY WITH CLUSTER BY cannot auto-generate stats on table with column event_ts due to unsupported type: timestamp. Disable stats auto-generation by setting 'spark.databricks.delta.liquidConversion.statsGeneration.enabled' to 'false' and retry the command again. SQLSTATE: 42000

转换限制

以下限制适用于 REPLACE PARTITIONED BY WITH CLUSTER BY 转换命令:

  • 不支持在 Lakeflow 管道中创建的流式表和物化视图。 若要使用液态聚类,必须更新管道定义,改为使用 CLUSTER BY,而不是使用 PARTITIONED BY。
  • 使用 Delta Sharing 和分区筛选的表不受支持。 有关 Delta Sharing 的分区过滤,请参阅 指定要共享的表分区。

删除群集密钥

要删除聚类分析键,请使用以下语法:

ALTER TABLE table_name CLUSTER BY NONE;

选择群集键

根据查询筛选器中最常用的列选择聚类键。 正确的键可显著提高数据跳过和查询性能。

Tip

Databricks 建议使用自动液体聚类分析根据查询模式智能选择聚类键。 请参阅 自动液体聚类。

关键选择指南

手动指定聚类键时,请根据查询筛选器中最常用的列来选择列。 可以按任意顺序定义聚类键。 如果两列高度相关,只需将其中一列做为聚类键。

要优先在某些列进行聚类,可以使用 分层聚类。

最多可以指定 四个聚类分析键。 对于较小的表(小于 10 TB),使用更多的聚类分析键在筛选单个列时可能会降低性能。 例如,使用四个键进行筛选比使用两个键进行筛选更糟糕。 但是,随着表大小的增加,对于单列查询而言,这种性能差异可以忽略不计。

聚类分析键必须是收集统计信息的列。 默认情况下,Delta Lake 表收集前 32 列的统计信息。 请参阅 “指定统计信息列”。

支持的数据类型

聚类分析支持以下数据类型用作聚类键:

  • Date
  • 时间戳
  • TimestampNTZ (Databricks Runtime 14.3 LTS 及更高版本)
  • String
  • 整数、长、短、字节
  • Float、Double、Decimal

您可以使用点表示法按 StructField 进行聚类,例如 CLUSTER BY (struct_col.field)。 嵌套结构字段支持任何深度,例如 CLUSTER BY (struct_col.nested.field)。 字段的数据类型必须是上述列表中受支持的类型之一。

无法按以下任一方式进行群集:

  • 复杂类型,例如 StructType, MapType或 ArrayType
  • MapType 和 ArrayType 元素,如 map_col['key'], array_col[0]或 map_col.key。

从分区或 Z 顺序迁移

Important

Databricks 建议您使用 REPLACE PARTITIONED BY WITH CLUSTER BY 命令进行自动转换。 请参阅 将分区表转换为液体聚类分析。

若要转换现有表,请考虑以下建议:

当前数据优化技术 有关群集键的建议
Hive 样式分区方法 使用分区列作为群集键。
Z 顺序索引 使用 ZORDER BY 列作为群集键。
Hive 样式分区和 Z 顺序 将分区列和 ZORDER BY 列用作群集键。
生成的用于减少基数的列(例如,时间戳的日期) 使用原始列作为群集键,不要创建生成的列。

使用分层聚类确定聚类键的优先级

在 Databricks Runtime 17.1 及更高版本中,可以将分层聚类与 OPTIMIZE 配合使用,通过提高某些聚类键的优先级来改进数据跳过。 例如,如果你之前按 event_date 对表进行了分区,并在 customer_id 上使用了 ZORDER,则应优先考虑 event_date,并将 customer_id 设置为标准聚类键。

分层聚类的工作原理

分层聚类先按优先级最高的列组织数据,然后按你指定的顺序按后续列排列。 剩余的聚类密钥均为标准聚类密钥。 当你手动设置分层聚类时,预测优化会尊重该配置,不会覆盖它。

要配置分层聚类,设置 delta.liquid.hierarchicalClusteringColumns 表属性。 属性中的每一列也必须是聚类键。 属性中列的顺序很重要: 第一列优先级最高。

分层聚类可能会提升经常按优先列进行筛选的查询的数据跳过效果。 指定基数较低的列以最大化数据跳跃率。 对于多个层级聚类键,从基数较低到更高基数排序。

警告

Databricks 建议将高基数列保留为标准聚类键,而非层次聚类键。 高基数层级聚类密钥会降低低优先级聚类密钥的聚类效果,并降低查询性能。

创建表

以下示例创建一个包含四个聚类键的表。 分层聚类首先按 store_id 对数据进行组织,然后按 event_date 进行组织。 customer_id和product_id列是标准的聚类键。

CREATE TABLE events (
  event_date DATE,
  store_id BIGINT,
  customer_id BIGINT,
  product_id BIGINT
)
CLUSTER BY (event_date, store_id, customer_id, product_id)
TBLPROPERTIES (
  'delta.liquid.hierarchicalClusteringColumns' = 'event_date,store_id'
);

写入表后,用 OPTIMIZE 指定的层级将新数据聚类。 请参阅如何触发聚类。

配置现有表

在现有的集群表上,使用 ALTER TABLE,然后运行 OPTIMIZE FULL ,使用指定的层级重新分组所有现有数据:

ALTER TABLE events SET TBLPROPERTIES (
  'delta.liquid.hierarchicalClusteringColumns' = 'event_date,store_id'
);

OPTIMIZE events FULL;

转换已分区的表

当你将 分区表转换为液体聚类时,分区列被设置为新的分层聚类键。 例如,如果一个表被划分为 (p1, p2),以下命令将表转换为液体聚类,并使用 p1 和 p2 作为分层聚类键, c1 以及 作为 c2 标准聚类键:

ALTER TABLE table_name
REPLACE PARTITIONED BY WITH CLUSTER BY (p1, p2, c1, c2);

转换后你不需要设置 delta.liquid.hierarchicalClusteringColumns 表格属性。

恢复标准聚类

要恢复到标准聚类,请取消表属性:

ALTER TABLE events UNSET TBLPROPERTIES (
  'delta.liquid.hierarchicalClusteringColumns'
);

自动液体聚类分析

在 Databricks Runtime 15.4 LTS 及更高版本中,可以为 Unity 目录托管的 Delta Lake 表启用自动液体聚类分析。 对于 Unity 目录管理的 Apache Iceberg v3 表,自动液体聚类分析需要 Databricks Runtime 18.0 及更高版本。 使用自动液体聚类功能,Azure Databricks 可以使用 CLUSTER BY AUTO 子句智能地选择聚类键来优化查询性能。

注释

具体化视图和流式处理表也支持自动液体聚类分析,包括 Lakeflow 管道和独立管道。 在管道或 SQL 定义中指定 CLUSTER BY AUTO 。

自动液体聚类分析的工作原理

自动液体聚类分析需要对自动键选择和聚类分析操作进行预测优化,并异步运行。

自动液体聚类分析根据使用模式应用智能优化:

  • 分析查询工作负载:Azure Databricks 对表的历史查询工作负载进行分析,并确定用于聚类的最佳候选列。
  • 适应更改:如果查询模式或数据分布随时间而变化,则自动液体聚类分析会选择新的键来优化性能。
  • 成本感知选择:Azure Databricks仅在预测的数据跳过改进带来的成本节约超过数据聚类成本时才更改聚类键。

由于以下原因,自动液体聚类分析可能不会选择密钥:

  • 表太小,无法受益于液体聚类分析。
  • 该表已经拥有一个有效的聚类方案,可能来源于之前的手动键,或者是与查询模式匹配的自然插入顺序。
  • 该表的查询并不频繁。
  • 您未使用 Databricks Runtime 15.4 LTS 或更高版本。

无论数据和查询特征如何,都可以为所有 Unity 目录托管表应用自动液体聚类分析。 启发式会决定选择聚类键是否具有成本效益。

Databricks Runtime 版本兼容性

可以从支持液体聚类分析的所有 Databricks Runtime 版本读取或写入启用了自动聚类分析的表。 但是,智能密钥选择依赖于 Databricks Runtime 15.4 LTS 中引入的元数据。

使用 Databricks Runtime 15.4 LTS 或更高版本来确保自动选择的键有利于所有工作负载,并在选择新键时考虑这些工作负载。

启用或关闭自动液体聚集

SQL

若要创建具有自动液体聚类分析的表,请执行以下操作:

CREATE OR REPLACE TABLE table1 (column01 int, column02 string) CLUSTER BY AUTO;

若要在现有表上启用自动液体聚类分析,包括具有手动指定的键的表:

ALTER TABLE table1 CLUSTER BY AUTO;

若要为键选择设置初始聚类分析列提示,请设置聚类分析键,然后启用自动聚类分析:

ALTER TABLE table1 CLUSTER BY (c1, c2);
ALTER TABLE table1 CLUSTER BY AUTO;

或者,使用 Python API 在单个操作中设置提示。

若要关闭自动液体聚类分析,请执行以下操作:

ALTER TABLE table1 CLUSTER BY NONE;

若要关闭自动液体聚类分析并指定聚类分析列,请执行以下操作:

ALTER TABLE table1 CLUSTER BY (column01, column02);

如果现有表已启用自动 Liquid Clustering,运行 CREATE OR REPLACE table_name 而不使用 CLUSTER BY AUTO 会关闭自动聚类,并且不会保留聚类列。 若要保留自动液体聚类以及之前选择的所有列,请在 replace 语句中包含 CLUSTER BY AUTO。 借助 CLUSTER BY AUTO,预测优化使用表的历史查询工作负荷来标识最佳聚类分析键。

Python

Python API 在 Databricks Runtime 16.4 及更高版本中提供。 只能在创建或替换表时使用Python。 使用 SQL 更改 clusterByAuto 现有表的状态。

若要创建具有自动液体聚类分析的表,请使用 DataFrameWriter:

df = spark.read.table("table1")
df.write
  .format("delta")
  .option("clusterByAuto", "true")
  .saveAsTable(...)

要使用 DataFrameWriter 为键选择设置初始聚类列提示,请执行以下操作:

df.write
  .format("delta")
  .clusterBy("clusteringColumn1", "clusteringColumn2")
  .option("clusterByAuto", "true")
  .saveAsTable(...)

若要创建具有自动液体聚类分析的表,请使用 DataFrameWriterV2:

df.writeTo(...).using("delta")
  .option("clusterByAuto", "true")
  .create()

要使用 DataFrameWriterV2 为键选择设置初始聚类列提示,请执行以下操作:

df.writeTo(...).using("delta")
  .clusterBy("clusteringColumn1", "clusteringColumn2")
  .option("clusterByAuto", "true")
  .create()

若要创建具有自动液体聚类分析的流式处理表,请执行以下操作:

spark.readStream.table("source_table")
  .writeStream
  .option("clusterByAuto", "true")
  .option("checkpointLocation", checkpointPath)
  .toTable("target_table")

若要为流式表中的键选择设置初始聚类列提示:

spark.readStream.table("source_table")
  .writeStream
  .clusterBy("column1", "column2")
  .option("clusterByAuto", "true")
  .option("checkpointLocation", checkpointPath)
  .toTable("target_table")

当你将 .clusterBy 用于群集键选择提示并与 .option('clusterByAuto', 'true') 一起使用时,其行为如下:

  • 如果这是首次设置自动液体聚类,则聚类列将设为 .clusterBy 中指定的列。
  • 如果这是一个已启用自动液态聚类的现有表,则仅接受一次 .clusterBy 提示。 例如,只有在表未设置聚簇列时,才会设置由 .clusterBy 指定的列。

Important

使用 DataFrame APIs 时,仅在使用 clusterByAuto 模式时才能设置overwrite 选项。 使用clusterByAuto模式时无法设置append。 此限制与手动设置聚类列时的限制相同。 只能在使用 overwrite 模式创建表或替换操作期间配置群集设置。

解决方法是,如果要在追加数据时更改 clusterByAuto 现有表的状态,请使用 SQL ALTER TABLE 命令独立于数据写入作修改群集配置。

检查是否启用了自动聚类分析

若要检查表是否启用了自动液体聚类分析,请使用 DESCRIBE TABLE 或 SHOW TBLPROPERTIES。

如果启用了自动液体聚类分析,则属性 clusterByAuto 设置为 true。 该clusteringColumns 属性显示自动或手动选择的目前的聚类列。

Limitations

自动液体聚类分析不适用于托管 Apache Iceberg v2 表。 Databricks Runtime 18.0 及更高版本支持托管 Apache Iceberg v3 表。

将数据写入聚类分析表

若要向聚类 Delta Lake 表写入数据,必须使用支持液态聚类所使用的所有 Delta 写入协议表功能的 Delta 写入客户端。 若要写入集群 Iceberg 表,可以使用 Unity Catalog 的 Iceberg REST Catalog API。 在 Azure Databricks 上,必须使用 Databricks Runtime 13.3 LTS 及更高版本。

支持写入时群集的操作

在写入时聚集的操作包括:

  • INSERT INTO 操作
  • CTAS 和 RTAS 语句
  • 来自 Parquet 格式的 COPY INTO
  • spark.write.mode("append")

群集的大小阈值

当事务中数据的大小满足阈值时,才会触发写入时的聚类操作。 这些阈值因聚类列的数量而异,且对于 Unity Catalog 托管表,这些阈值低于其他 Delta Lake 表。

聚类列数 Unity Catalog 托管表的阈值大小 其他 Delta Lake 表的阈值大小
1 64 MB 256 MB
2 256 MB 1GB
3 512 MB 2 GB
4 1GB 4 GB

由于并非所有操作都应用 liquid clustering,因此 Databricks 建议经常运行 OPTIMIZE,以确保所有数据都能高效地进行聚类。

流式处理工作负荷

将 Spark 配置 spark.databricks.delta.liquid.eagerClustering.streaming.enabled 设置为 true 时,结构化流处理工作负载支持在写入时进行分区。 仅当最近五次流处理更新中的至少一次超出上表中的大小阈值时,才会触发这些工作负荷的聚类。

如何触发聚类

预测优化会自动为已启用的表运行 OPTIMIZE 命令。

若要触发聚类分析,必须使用 Databricks Runtime 13.3 LTS 或更高版本。 Databricks 建议对大型表执行 OPTIMIZE 时使用 Databricks Runtime 17.3 LTS 及以上版本,以获得更快的性能。 在您的表上使用 OPTIMIZE 命令:

OPTIMIZE table_name;

液体聚类分析是 增量的,这意味着 OPTIMIZE 仅根据需要重写数据以适应需要聚类分析的数据。 OPTIMIZE 不会使用与群集数据不匹配的群集键重写数据文件。 请参阅 强制重聚类化。

如果不使用预测优化,Databricks 建议定期安排 OPTIMIZE 作业来对数据进行聚簇。 对于经历多次更新或插入的表,Databricks 建议每隔一或两个小时安排一次 OPTIMIZE 作业。 由于 liquid 聚类是增量的,因此大多数用于聚类表的 OPTIMIZE 作业运行速度很快。

强制重新分组

在 Databricks Runtime 16.4 LTS 及更高版本中,可以使用以下语法强制重新聚集表中的所有记录:

OPTIMIZE table_name FULL;

Important

运行 OPTIMIZE <table_name> FULL 会根据需要重新对所有现有数据进行聚类。 对于之前未按指定键聚类的大型表,此操作可能需要数小时。

首次启用群集或更改群集密钥时,请运行 OPTIMIZE <table_name> FULL。 如果之前已运行 OPTIMIZE <table_name> FULL,并且群集键没有更改,则 OPTIMIZE <table_name> FULL 的运行方式与 OPTIMIZE 相同。 在此方案中, OPTIMIZE 使用增量方法,仅重写以前未压缩的文件。 始终使用 OPTIMIZE <table_name> FULL 来确保数据布局反映当前的聚类键。

部分重聚类

在 Databricks Runtime 18.1 及更高版本中,可以使用 OPTIMIZE <table_name> FULL WHERE <predicate> 强制对记录的一个子集重新聚集。 如果文件的范围中的任何部分与谓词重叠,则将该文件包含在内。 请参阅参数。

OPTIMIZE events FULL WHERE event_date >= '2025-01-01';

从聚类分析表读取数据

您可以使用任何支持读取删除向量的 Delta Lake 客户端来读取聚簇 Delta Lake 表中的数据。 使用 Iceberg REST 目录 API,可以在聚集的 Iceberg 表中读取数据。 当筛选聚类键时,Liquid 聚类通过自动跳过数据来提高查询性能。

SELECT * FROM table_name WHERE cluster_key_column_name = "some_value";

管理群集密钥

了解如何对表进行聚类分析

可以使用 DESCRIBE 命令查看表的聚类分析键,如以下示例所示:

DESCRIBE TABLE table_name;

DESCRIBE DETAIL table_name;

更改聚类键

可以通过运行 ALTER TABLE 命令随时更改表的聚类分析键,如以下示例所示:

ALTER TABLE table_name CLUSTER BY (new_column1, new_column2);

更改聚类分析键后,后续 OPTIMIZE 和写入操作将使用新的聚类分析方法,但不会重写现有数据。 若要使用更新的群集键重写现有数据,请参阅 强制重新聚集。

还可以通过将键设置为 NONE 来关闭聚类分析,如以下示例所示:

ALTER TABLE table_name CLUSTER BY NONE;

将群集键设置为 NONE 不会重写簇数据,但会阻止将来 OPTIMIZE 操作使用群集键。

使用来自外部引擎的液体聚类分析

可以从外部 Iceberg 引擎在托管的 Iceberg 表上启用液体聚类分析。 若要启用液体聚类分析,请在创建表时指定分区列。 Unity 目录将分区解释为聚类键。 例如,在 OSS Spark 中运行以下命令:

CREATE OR REPLACE TABLE main.schema.icebergTable
PARTITIONED BY c1;

若要关闭液体聚类,请执行以下操作:

ALTER TABLE main.schema.icebergTable DROP PARTITION FIELD c2;

若要使用 Iceberg 分区演化更改聚类键,请执行以下操作:

ALTER TABLE main.schema.icebergTable ADD PARTITION FIELD c2;

如果使用分桶转换指定分区,Unity Catalog 会删除表达式,并将该列用作聚类键:

CREATE OR REPLACE TABLE main.schema.icebergTable
PARTITIONED BY (bucket(c1, 10));

表与液态聚类的兼容性

液体聚类使用 Delta Lake 表功能,这些功能需要特定的 Databricks Runtime 版本才能进行读取和写入。 默认情况下,在 Databricks Runtime 14.3 LTS 及更高版本中使用液体聚类分析创建的表使用检查点 V2。 可以在 Databricks Runtime 13.3 LTS 及更高版本中使用检查点 V2 来读取和写入表格。 请参阅 检查点 V2。

若要支持使用 Databricks Runtime 12.2 LTS 到 13.2 的读取器,请禁用检查点 V2 并降级表协议。 请参阅 降级到经典。

替代默认功能启用(可选)

您可以在启用液态聚类时覆盖 Delta Lake 表功能的默认启用设置。 这可以防止升级与这些表功能关联的读取器和编写器协议。 必须具有现有表才能完成以下步骤:

  1. 使用 ALTER TABLE 来设置可关闭一个或多个功能的表属性。 例如,若要关闭删除向量,请运行以下命令:

    ALTER TABLE table_name SET TBLPROPERTIES ('delta.enableDeletionVectors' = false);
    
  2. 通过运行以下命令,为表启用液体群集:

    ALTER TABLE <table_name>
    CLUSTER BY (<clustering_columns>)
    

下表介绍了可以替代的 Delta 功能,以及启用如何影响与 Databricks Runtime 版本的兼容性:

Delta 功能 运行时兼容性 用于覆盖启用状态的属性 关闭时对液体聚类的影响
删除矢量 读取和写入需要 Databricks Runtime 12.2 LTS 及更高版本。 'delta.enableDeletionVectors' = false 关闭删除向量也会关闭行级并发,使事务和群集操作更有可能发生冲突。 请参阅 行级并发。
DELETE、MERGE 和 UPDATE 命令可能运行较慢。
行跟踪 写入操作需要 Databricks Runtime 13.3 LTS 及更高版本。 可以从任何 Databricks Runtime 版本进行读取。 'delta.enableRowTracking' = false 关闭行跟踪还会关闭行级并发,使事务和群集操作更有可能发生冲突。 请参阅 行级并发。
检查点 V2 读取和写入操作需要 Databricks Runtime 13.3 LTS 及更高版本。 'delta.checkpointPolicy' = 'classic' 对液体团聚行为没有影响。 请参阅 检查点 V2。

Limitations

  • Databricks Runtime 15.1 及以下版本:写入时聚类不允许源查询包含筛选器、联接或聚合。
  • Databricks Runtime 15.4 LTS 及更低版本:无法通过启用流动簇来使用结构化流写入进行表创建。 可以使用结构化流式处理将数据写入启用了液体聚类的现有表。
  • Apache Iceberg v2:托管 Apache Iceberg v2 表不支持行级并发,因为不支持删除矢量和行跟踪。