扩展DDL语法
前提条件
需已存在Iceberg表,例如,执行以下命令创建表:
CREATE TABLE prod.db.sample (id bigint, data string, category string, ts timestamp, ts_day timestamp) USING iceberg PARTITIONED BY (category);
基本语法
在Spark中使用Iceberg SQL扩展时,可使用以下命令:
ALTER TABLE ... ADD PARTITION FIELD;
ALTER TABLE ADD/REPLACE/DROP PARTITION FIELD
- ADD PARTITION FIELD
Iceberg支持通过ADD PARTITION FIELD向分区规范中添加新的分区字段:
ALTER TABLE prod.db.sample ADD PARTITION FIELD id;
同时支持分区转换操作:
- 示例一:
ALTER TABLE prod.db.sample ADD PARTITION FIELD bucket(16, id);
- 示例二:
ALTER TABLE prod.db.sample ADD PARTITION FIELD truncate(4, data);
- 示例三:
ALTER TABLE prod.db.sample ADD PARTITION FIELD year(ts);
添加分区字段属于元数据操作,不会更改任何现有表数据。新数据将按照新的分区方式写入,但现有数据仍保持原有的分区布局。在元数据表中,旧数据文件的新分区字段值将为null。
当表的分区方式发生变化时,动态分区覆盖行为也会随之改变,因为动态覆盖会隐式替换分区。
- 示例一:
- DROP PARTITION FIELD
可使用DROP PARTITION FIELD移除分区字段。即使分区被移除,对应的列仍会保留在表的Schema 中。
删除分区字段属于元数据操作,不会更改任何现有表数据。新数据将按照新的分区方式写入,但现有数据仍保持原有的分区布局。
- 移除分区字段:
- 示例一:
ALTER TABLE prod.db.sample DROP PARTITION FIELD category;
- 示例二:
ALTER TABLE prod.db.sample DROP PARTITION FIELD bucket(16, id);
- 示例三:
ALTER TABLE prod.db.sample DROP PARTITION FIELD truncate(4, data);
- 示例四:
ALTER TABLE prod.db.sample DROP PARTITION FIELD year(ts);
- 示例一:
- 移除分区字段:
- REPLACE PARTITION FIELD
通过REPLACE PARTITION FIELD可在单次元数据更新中,用新的分区字段ts_day替换原有分区字段year(ts):
- 示例一:
ALTER TABLE prod.db.sample REPLACE PARTITION FIELD year(ts) WITH ts_day;
- 示例二:
ALTER TABLE prod.db.sample REPLACE PARTITION FIELD year(ts) WITH ts_day AS day_of_ts;
- 示例一:
ALTER TABLE WRITE/LOCALLY ORDERED BY
- WRITE ORDERED BY
Iceberg表可配置排序规则,部分引擎会依据该规则,在向表写入数据时自动对数据进行排序。例如,Spark中的MERGE INTO操作会使用表的排序规则。
可使用WRITE ORDERED BY子句为表设置写入排序规则,示例如下:
- 示例一:
ALTER TABLE prod.db.sample WRITE ORDERED BY category, id;
- 示例二:
ALTER TABLE prod.db.sample WRITE ORDERED BY category ASC, id DESC;
- 示例三:
ALTER TABLE prod.db.sample WRITE ORDERED BY category ASC NULLS LAST, id DESC NULLS FIRST;
WRITE ORDERED BY用于设置全局排序规则,会对跨任务的行进行排序,类似于在INSERT命令中使用ORDER BY,例如:INSERT INTO prod.db.sample SELECT id, data, category, ts FROM {其他表} ORDER BY ts, category;若只需在每个任务内排序(而非跨任务排序),可使用LOCALLY ORDERED BY:
ALTER TABLE prod.db.sample WRITE LOCALLY ORDERED BY category, id;
可使用UNORDERED取消表的排序顺序:
ALTER TABLE prod.db.sample WRITE UNORDERED;
- 示例一:
- WRITE DISTRIBUTED BY PARTITION
WRITE DISTRIBUTED BY PARTITION用于指定每个分区由单个写入器(writer)处理,其默认实现方式为哈希分布。
ALTER TABLE prod.db.sample WRITE DISTRIBUTED BY PARTITION;
DISTRIBUTED BY PARTITION可与LOCALLY ORDERED BY结合使用,实现按分区分布数据,同时在每个任务内对行进行本地排序:
ALTER TABLE prod.db.sample WRITE DISTRIBUTED BY PARTITION LOCALLY ORDERED BY category, id;
ALTER TABLE SET/DROP IDENTIFIER FIELDS(MRS 3.6.0-LTS及之后版本)
执行以下命令在prod数据库的db模式中创建一个名为sample的Iceberg表,并按category列进行分区:
CREATE TABLE prod.db.sample (id bigint NOT NULL, data string NOT NULL, category string, ts timestamp, ts_day timestamp) USING iceberg PARTITIONED BY (category);
- SET IDENTIFIER FIELDS
Iceberg支持通过SET IDENTIFIER FIELDS为表规范设置标识字段。如果Spark表配置了标识字段,该表可支持Flink SQL的更新插入(upsert)操作。
Iceberg不支持直接通过ALTER COLUMN id SET NOT NULL将现有可空字段改成非空字段。
- 示例一,需确保字段无空值:
ALTER TABLE prod.db.sample SET IDENTIFIER FIELDS id;
- 示例二:
ALTER TABLE prod.db.sample SET IDENTIFIER FIELDS id, data;
标识字段在创建或添加时,必须是非空列(NOT NULL)。后续执行的ALTER TABLE ... SET IDENTIFIER FIELDS语句会覆盖之前的标识字段设置。
- 示例一,需确保字段无空值:
- DROP IDENTIFIER FIELDS
可使用DROP IDENTIFIER FIELDS移除标识字段,且即使标识字段被移除,对应的列仍会保留在表的Schema中。
- 示例一,需确保字段无空值:
ALTER TABLE prod.db.sample DROP IDENTIFIER FIELDS id;
- 示例二:
ALTER TABLE prod.db.sample DROP IDENTIFIER FIELDS id, data;
- 示例一,需确保字段无空值: