功能概述
MaxCompute支持将Apache Iceberg表存储在阿里云对象存储(OSS)上,并通过MaxCompute统一管理元数据、权限和数据生命周期,实现高效查询、写入和管理。Iceberg表兼容Spark、Flink、Trino、Presto等开源引擎,支持多引擎共享同一份数据,适用于湖仓开放(Lakehouse)架构。
通过支持Iceberg开放表格式,MaxCompute打破数据孤岛,使数仓与Spark、Flink、Hive等开源引擎无缝共享同一份Iceberg表数据。用户可按需选择计算引擎,避免绑定单一技术栈,同时利用Iceberg的开放标准保障数据资产的长期可移植性,并支持包括跨云场景在内的组织协同。
MaxCompute管理的Iceberg表具备以下特性:
Iceberg湖表数据管理:
通过MaxCompute SQL创建和读写OSS上的Iceberg表,支持建表、删表、读写、时间旅行(Time Travel)、Schema Evolution和Partition Evolution。
自动化后台运维:
MaxCompute 提供内置的 Iceberg 表优化服务,包括小文件合并(Compaction)、过期快照清理(Expire Snapshots)、元数据文件归档等,无需手动调度或运维,显著降低使用复杂度。
元数据一致性保障:
表的元数据由 MaxCompute Metastore(MaxMeta) 统一维护,确保所有写入操作满足 ACID 事务语义。外部引擎若需写入 Iceberg 表,需通过 MaxCompute 提供的 Storage Write API 或使用 MaxCompute 内置计算引擎,避免多写入端导致的元数据冲突与数据不一致。
开放生态集成:
开源计算引擎(如 Trino、Presto、Spark、Flink、Doris 等)可以使用Iceberg兼容的方式访问MaxCompute管理的Iceberg表,实现低延迟、高并发的多引擎查询。
统一权限管理:通过MaxCompute统一管理的元数据服务和权限体系,数据湖的RAM权限体系和数仓权限体系可以统一定义,从而提供数仓的企业级权限管理能力。
注意事项
对MaxCompute管理的Iceberg表执行以下操作会导致数据丢失或不可读:
禁止操作 | 后果 | 正确做法 |
通过非MaxCompute的写接口(例如storage api 或sql等)在OSS上更新或修改管理目录下的Iceberg表数据 | 在外部修改或替换 Iceberg数据,会导致表无法通过一致性检查,并且变得不可读从而查询失败。 | 仅通过MaxCompute SQL修改数据 |
向OSS的Iceberg 表管理路径上传数据或添加新文件 | 上传的文件会被后台服务作为孤儿文件回收 | 不在管理路径下上传数据 |
基于同一OSS路径多次创建MaxCompute管理的Iceberg表 | 各表的垃圾回收进程会互相删除对方的文件 | 每个表使用不同的OSS路径,若在同一目录多次建表,需使用干净路径重新建表并copy数据到新表,避免数据丢失。 |
在具有父子目录关系的OSS路径上创建不同的MaxCompute管理的Iceberg表 | 每个表的后台垃圾回收进程都会将另一个表的文件视为脏数据或者孤儿文件,并将其删除,从而导致数据丢失。 | 避免在存在父子关系的路径上分别建表,每个MaxCompute管理的Iceberg 表使用不同的路径。 |
创建表
语法结构
CREATE ICEBERG TABLE [IF NOT EXISTS] <table name> (
<col_name> <data_type>,
...
)
[PARTITIONED BY (<partitionExpression>)]
WITH CONNECTION <connection name>
OPTIONS(
location='<oss_location>'
)
;参数说明
使用示例
CREATE ICEBERG TABLE mc_iceberg_table (
id bigint COMMENT '用户唯一标识ID',
name string COMMENT '用户姓名',
age bigint COMMENT '用户年龄',
gender string COMMENT '用户性别',
height float COMMENT '用户身高',
birthday date COMMENT '用户生日',
phone_number string COMMENT '用户电话号码',
email string COMMENT '用户电子邮箱',
address string COMMENT '用户地址',
salary decimal(18, 2) COMMENT '用户薪水',
create_time timestamp COMMENT '用户信息创建时间',
update_time timestamp COMMENT '用户信息更新时间',
is_deleted boolean COMMENT '用户信息是否被删除的标志位',
dt string COMMENT '分区字段'
)
PARTITIONED BY (dt)
WITH CONNECTION <connection name>
OPTIONS(
location='oss://<oss bucket>/Demo-iceberg/',
comment = '测试表'
);写入数据
MaxCompute写入语法详情,请参见语法说明。
示例如下:
SET odps.sql.type.system.odps2=true; SET odps.sql.decimal.odps2=true; INSERT INTO mc_iceberg_table VALUES (1, '张三', 18, '男', cast (178.56 as float), DATE '1990-01-01', '13800000000', 'zhangsan@example.com', '北京市海淀区', 5000.00, TIMESTAMP '2023-04-19 11:32:00', TIMESTAMP '2023-04-19 11:32:00', false,'20260402'), (2, '李四', 20, '女', cast (162.70 as float), DATE '1992-02-02', '13900000000', 'lisi@example.com', '上海市浦东新区', 6000.00, TIMESTAMP '2023-04-19 11:32:00', TIMESTAMP '2023-04-19 11:32:00',false,'20260401'), (3, '王五', 22, '男', cast (185.21 as float), DATE '1994-03-03', '14000000000', 'wangwu@example.com', '深圳市南山区', 7000.00, TIMESTAMP '2023-04-19 11:32:00', TIMESTAMP '2023-04-19 11:32:00', false,'20260403') ;
查询分析
基础查询
SELECT语法详情,请参见语法说明。
示例如下:
SELECT * FROM mc_iceberg_table; -- 返回结果如下: +------------+------+------------+--------+--------+----------+--------------+-------+---------+--------+-------------+-------------+------------+----+ | id | name | age | gender | height | birthday | phone_number | email | address | salary | create_time | update_time | is_deleted | dt | +------------+------+------------+--------+--------+----------+--------------+-------+---------+--------+-------------+-------------+------------+----+ | 1 | 张三 | 18 | 男 | 178.56 | 1990-01-01 | 13800000000 | zhangsan@example.com | 北京市海淀区 | 5000 | 2023-04-19 03:32:00 | 2023-04-19 03:32:00 | false | 20260402 | | 2 | 李四 | 20 | 女 | 162.7 | 1992-02-02 | 13900000000 | lisi@example.com | 上海市浦东新区 | 6000 | 2023-04-19 03:32:00 | 2023-04-19 03:32:00 | false | 20260401 | | 3 | 王五 | 22 | 男 | 185.21 | 1994-03-03 | 14000000000 | wangwu@example.com | 深圳市南山区 | 7000 | 2023-04-19 03:32:00 | 2023-04-19 03:32:00 | false | 20260403 | +------------+------+------------+--------+--------+----------+--------------+-------+---------+--------+-------------+-------------+------------+----+
Time Travel 历史版本查询
Time Travel 查询MaxCompute管理的Iceberg表,回溯到源表某个历史时间或者版本进行历史Snapshot查询。可通过[TIMESTAMP | VERSION AS OF expr]来配置具体的查询方式。
SHOW HISTORY
可通过 SHOW HISTORY 列出 snapshot_id 与 committed_at。
语法
SHOW HISTORY FOR TABLE <table_name>;参数说明
table_name:表名。
使用示例
SHOW HISTORY FOR TABLE user_info_test; -- 返回结果如下 committed_at snapshot_id parent_id operation manifest_list summary 1793701639053000 9223372035110209012 null append oss://bucket/manage_iceberg_table/user_info_test/metadata/snap-9223372035110209012-1-55508b08-676a-48c6-9923-efdd2ea423cb.avro [{"key":"odps.task.instance.name","value":"2026110310270359gv6arkmh5ze5"},{"key":"added-files-size","value":"2316"},{"key":"total-equality-deletes","value":"0"},{"key":"total-records","value":"2"},{"key":"iceberg-version","value":"Apache Iceberg 1.6.1 (commit 8e9d59d299be42b0bca9461457cd1e95dbaad086)"},{"key":"changed-partition-count","value":"1"},{"key":"added-data-files","value":"1"},{"key":"total-files-size","value":"2316"},{"key":"total-position-deletes","value":"0"},{"key":"total-data-files","value":"1"},{"key":"total-delete-files","value":"0"},{"key":"added-records","value":"2"}] 1793701689430000 9104544753594776504 9223372035110209012 append oss://bucket/manage_iceberg_table/user_info_test/metadata/snap-9104544753594776504-1-5bed9def-2147-4070-9421-da287d5b1dc8.avro [{"key":"total-files-size","value":"4584"},{"key":"total-equality-deletes","value":"0"},{"key":"total-records","value":"3"},{"key":"iceberg-version","value":"Apache Iceberg 1.6.1 (commit 8e9d59d299be42b0bca9461457cd1e95dbaad086)"},{"key":"changed-partition-count","value":"1"},{"key":"added-data-files","value":"1"},{"key":"total-position-deletes","value":"0"},{"key":"total-delete-files","value":"0"},{"key":"total-data-files","value":"2"},{"key":"added-records","value":"1"},{"key":"added-files-size","value":"2268"},{"key":"odps.task.instance.name","value":"20261103102754425gbx1wpz04ti"}] 1793758383410000 9223372036507144701 9104544753594776504 append oss://bucket/manage_iceberg_table/user_info_test/metadata/snap-9223372036507144701-1-521017a8-0c05-4844-bb74-75663d02b294.avro [{"key":"total-position-deletes","value":"0"},{"key":"added-data-files","value":"1"},{"key":"changed-partition-count","value":"1"},{"key":"iceberg-version","value":"Apache Iceberg 1.6.1 (commit 8e9d59d299be42b0bca9461457cd1e95dbaad086)"},{"key":"total-equality-deletes","value":"0"},{"key":"total-records","value":"4"},{"key":"added-records","value":"1"},{"key":"added-files-size","value":"2303"},{"key":"odps.task.instance.name","value":"20261104021242439gag3a4kh5ze5"},{"key":"total-data-files","value":"3"},{"key":"total-delete-files","value":"0"},{"key":"total-files-size","value":"6887"}] 1793758503143000 9223372036251690789 9223372036507144701 append oss://bucket/manage_iceberg_table/user_info_test/metadata/snap-9223372036251690789-1-ba5e5d25-4844-4624-b6e9-63e19e558238.avro [{"key":"total-equality-deletes","value":"0"},{"key":"added-data-files","value":"1"},{"key":"iceberg-version","value":"Apache Iceberg 1.6.1 (commit 8e9d59d299be42b0bca9461457cd1e95dbaad086)"},{"key":"changed-partition-count","value":"1"},{"key":"added-records","value":"1"},{"key":"added-files-size","value":"2300"},{"key":"odps.task.instance.name","value":"2026110402143563g69g9k2a4385"},{"key":"total-records","value":"5"},{"key":"total-files-size","value":"9187"},{"key":"total-delete-files","value":"0"},{"key":"total-data-files","value":"4"},{"key":"total-position-deletes","value":"0"}] 1793759378679000 5293593429568553902 9223372036251690789 append oss://bucket/manage_iceberg_table/user_info_test/metadata/snap-5293593429568553902-1-636398c5-cc19-4554-bcdf-8e4654924c7f.avro [{"key":"odps.task.instance.name","value":"20261104022908984goqofj5ywhj"},{"key":"added-data-files","value":"1"},{"key":"added-records","value":"1"},{"key":"added-files-size","value":"2329"},{"key":"changed-partition-count","value":"1"},{"key":"total-records","value":"6"},{"key":"total-files-size","value":"11516"},{"key":"total-data-files","value":"5"},{"key":"total-delete-files","value":"0"},{"key":"total-position-deletes","value":"0"},{"key":"total-equality-deletes","value":"0"},{"key":"iceberg-version","value":"Apache Iceberg 1.6.1 (commit 8e9d59d299be42b0bca9461457cd1e95dbaad086)"}]
TIMESTAMP AS OF expr
回溯到源表某个历史时间。
语法
SELECT * FROM <table_name> TIMESTAMP AS OF <expr>;参数说明
table_name:表名。
TIMESTAMP AS OF为固定语法格式,代表根据历史时间查询历史snapshot数据 。expr的取值类型为MaxCompute标准的TIMESTAMP类型,例如2026-11-04 10:00:00.123。可根据SHOW HISTORY返回结果中的committed_at字段转换成TIMESTAMP的值,再进行回溯。
使用示例
SET odps.sql.type.system.odps2=true; SELECT FROM_UNIXTIME(1793701689); -- 去掉1793701639053000后6位 -- -- TIMESTAMP AS OF expr:按时间戳(会话时区,毫秒精度) SELECT * FROM user_info_test TIMESTAMP AS OF '2026-11-03 18:28:09'; -- 返回结果如下,当前表中的数据有6条,下方SQL查询第二次插入数据后的快照 +------------+----------+------------+------------+-------+--------+---------------+ | user_id | username | age | salary | email | status | register_time | +------------+----------+------------+------------+-------+--------+---------------+ | 1001 | NULL | 25 | 8000.0 | zhangsan@email.com | ACTIVE | 2026-11-01 10:30:00 | | 1002 | NULL | 30 | 12000.0 | lisi@email.com | ACTIVE | 2026-11-02 14:20:00 | +------------+----------+------------+------------+-------+--------+---------------+ -- 当前查询表内容 +------------+----------+------------+------------+-------+--------+---------------+ | user_id | username | age | salary | email | status | register_time | +------------+----------+------------+------------+-------+--------+---------------+ | 1001 | NULL | 25 | 8000.0 | zhangsan@email.com | ACTIVE | 2026-11-01 10:30:00 | | 1002 | NULL | 30 | 12000.0 | lisi@email.com | ACTIVE | 2026-11-02 14:20:00 | | 1004 | 赵六 | 32 | 11000.0 | zhaoliu@email.com | INACTIVE | 2026-11-03 16:40:00 | | 1003 | 王五 | 28 | 9500.0 | wangwu@email.com | ACTIVE | 2026-11-03 09:15:00 | | 1004 | 赵六 | 32 | 11000.0 | zhaoliu@email.com | INACTIVE | 2026-11-03 16:40:00 | | 1005 | 孙七 | 35 | 15000.0 | sunqi@email.com | ACTIVE | 2026-11-04 08:20:00 | +------------+----------+------------+------------+-------+--------+---------------+
VERSION AS OF expr
回溯到源表某个版本。
语法
SELECT * FROM <table_name> VERSION AS OF <expr>;参数说明
table_name:表名。
VERSION AS OF为固定语法格式,代表根据历史数据操作的版本号(version)查询历史Snapshot数据。expr返回类型为MaxCompute的bigint整型,此处写SHOW HISTORY FOR TABLE <table_name>;的snapshot_id字段值。
使用示例
SELECT * FROM t VERSION AS OF 9223372035110209012; -- 返回结果如下,当前表中的数据有6条,下方SQL查询首次插入数据后的快照 +------------+----------+------------+------------+-------+--------+---------------+ | user_id | username | age | salary | email | status | register_time | +------------+----------+------------+------------+-------+--------+---------------+ | 1001 | NULL | 25 | 8000.0 | zhangsan@email.com | ACTIVE | 2026-11-01 10:30:00 | | 1002 | NULL | 30 | 12000.0 | lisi@email.com | ACTIVE | 2026-11-02 14:20:00 | +------------+----------+------------+------------+-------+--------+---------------+ -- 当前查询表内容 +------------+----------+------------+------------+-------+--------+---------------+ | user_id | username | age | salary | email | status | register_time | +------------+----------+------------+------------+-------+--------+---------------+ | 1001 | NULL | 25 | 8000.0 | zhangsan@email.com | ACTIVE | 2026-11-01 10:30:00 | | 1002 | NULL | 30 | 12000.0 | lisi@email.com | ACTIVE | 2026-11-02 14:20:00 | | 1004 | 赵六 | 32 | 11000.0 | zhaoliu@email.com | INACTIVE | 2026-11-03 16:40:00 | | 1003 | 王五 | 28 | 9500.0 | wangwu@email.com | ACTIVE | 2026-11-03 09:15:00 | | 1004 | 赵六 | 32 | 11000.0 | zhaoliu@email.com | INACTIVE | 2026-11-03 16:40:00 | | 1005 | 孙七 | 35 | 15000.0 | sunqi@email.com | ACTIVE | 2026-11-04 08:20:00 | +------------+----------+------------+------------+-------+--------+---------------+
Iceberg外部表与MaxCompute管理的Iceberg表对比
维度 | Iceberg外部表(External) | MaxCompute管理的Iceberg表(Managed) |
建表语句 | | |
表生命周期 | MaxCompute仅建立映射关系。 DROP TABLE只删除元数据,不删除OSS数据。 | MaxCompute负责元数据和OSS数据全生命周期管理。 建表时指定的OSS目录必须为空。 |
元数据及数据治理 | 与普通外部表一致 | 提供高性能metadata caching能力 |
数据开放性(开源引擎读写) | 读写一致性依赖Iceberg表格式自身保障 | 由MaxCompute保障数据读写一致性。开源引擎可直读OSS,或通过MaxCompute Storage API读写。 |
湖表维护 | 用户自行维护 | 后台自动维护:
|
支持数据类型
Iceberg数据类型 | MaxCompute数据类型 | 读写支持 |
Types.BooleanType | BOOLEAN | |
Types.IntegerType | INT | |
Types.LongType | BIGINT | |
Types.FloatType | FLOAT | |
Types.DoubleType | DOUBLE | |
Types.DecimalType | DECIMAL(precision, scale)
| |
Types.DateType | DATE | |
Types.TimeType | BIGINT
| |
Types.TimestampType | TIMESTAMP_NTZ | |
Types.TimestampType_z | TIMESTAMP | |
Types.StringType | STRING | |
Types.UUIDType | BINARY | |
Types.FixedType | BINARY | |
Types.BinaryType | BINARY | |
TypeID.STRUCT | STRUCT | |
TypeID.LIST | ARRAY | |
TypeID.MAP | MAP | |
不涉及 | TINYINT\SMALLINT\VARCHAR(n)\CHAR(n)\DATETIME\JSON | 不涉及 |
支持UPDATE/DELETE
Managed Iceberg Table 首次支持通过标准 DML 语句对数据进行行级更新和删除:
优化器会把 UPDATE 拆分为 DELETE 和 INSERT 两个子流程,并在同一事务内原子提交,即在同一个快照中同时提交 data manifests 和 delete manifests。
支持分区表。
UPDATE 或 DELETE 一行都没命中时,不会生成空快照。
注意事项
目前读取时合并 Delete 文件仍需走 Java 路径,因此查询前需执行以下命令:
SET odps.sql.iceberg.native.enabled=false;如果分区表的分区定义中包含时间函数,暂不支持 UPDATE 操作。
使用示例
创建测试表并插入数据。
CREATE ICEBERG TABLE data_process_log_nopt2 ( file_id BIGINT, file_path STRING, file_size BIGINT, process_status STRING, error_message STRING, retry_count INT, process_time TIMESTAMP, create_time TIMESTAMP ) WITH CONNECTION iceberg_connection OPTIONS( location='oss://oss-cn-<region>-internal.aliyuncs.com/<bucket path>/' ); -- 插入处理记录 INSERT INTO data_process_log_nopt2 VALUES (4001, 'oss://bucket/data/file1.csv', 1048576, 'PENDING', NULL, 0, NULL, TIMESTAMP '2026-11-03 08:00:00'), (4002, 'oss://bucket/data/file2.csv', 2097152, 'PENDING', NULL, 0, NULL, TIMESTAMP '2026-11-03 08:05:00'); -- 查询测试表 SELECT * FROM data_process_log_nopt2; -- 返回结果如下: +------------+-----------+------------+----------------+---------------+-------------+--------------+-------------+ | file_id | file_path | file_size | process_status | error_message | retry_count | process_time | create_time | +------------+-----------+------------+----------------+---------------+-------------+--------------+-------------+ | 4001 | oss://bucket/data/file1.csv | 1048576 | PENDING | NULL | 0 | NULL | 2026-11-03 08:00:00 | | 4002 | oss://bucket/data/file2.csv | 2097152 | PENDING | NULL | 0 | NULL | 2026-11-03 08:05:00 | +------------+-----------+------------+----------------+---------------+-------------+--------------+-------------+标记数据。
-- 标记处理完成 UPDATE data_process_log_nopt2 SET process_status = 'COMPLETED', error_message = NULL WHERE file_id = 4001 AND process_status = 'PENDING'; -- 查询测试表 SELECT * FROM data_process_log_nopt2; -- 返回结果如下: +------------+-----------+------------+----------------+---------------+-------------+--------------+-------------+ | file_id | file_path | file_size | process_status | error_message | retry_count | process_time | create_time | +------------+-----------+------------+----------------+---------------+-------------+--------------+-------------+ | 4002 | oss://bucket/data/file2.csv | 2097152 | PENDING | NULL | 0 | NULL | 2026-11-03 08:05:00 | | 4001 | oss://bucket/data/file1.csv | 1048576 | COMPLETED | NULL | 0 | NULL | 2026-11-03 08:00:00 | +------------+-----------+------------+----------------+---------------+-------------+--------------+-------------+删除数据。
-- 删除失败且超过重试次数的记录 DELETE FROM data_process_log_nopt2 WHERE process_status = 'PENDING'; -- 查询测试表 SELECT * FROM data_process_log_nopt2; -- 返回结果如下: +------------+-----------+------------+----------------+---------------+-------------+--------------+-------------+ | file_id | file_path | file_size | process_status | error_message | retry_count | process_time | create_time | +------------+-----------+------------+----------------+---------------+-------------+--------------+-------------+ | 4001 | oss://bucket/data/file1.csv | 1048576 | COMPLETED | NULL | 0 | NULL | 2026-11-03 08:00:00 | +------------+-----------+------------+----------------+---------------+-------------+--------------+-------------+
支持Schema Evolution
数据类型变更仅支持 Iceberg 规范的类型晋升矩阵中允许的基本类型(primitive type)转换。不兼容的类型变更会报错。更多详情,请参见列操作命令。
操作类型 | 是否支持 |
添加列 | |
删除列 | |
修改列顺序 | |
更改列数据类型 | |
修改列名 | |
修改列注释 | |
修改列的非空属性 |
支持Partition Evolution
支持以Iceberg生态的分区演进。使用示例如下:
ALTER TABLE t ADD PARTITION FIELDS c1; -- identity
ALTER TABLE t ADD PARTITION FIELDS bucket(10, id) AS id_bucket;
ALTER TABLE t REPLACE PARTITION FIELDS c1 WITH bucket(5, c3) AS bucket_c3;
ALTER TABLE t REPLACE PARTITION FIELDS year(ts) WITH month(ts);
ALTER TABLE t DROP PARTITION FIELDS region;可在分区演进操作完成后,在OSS数据的data目录下看分区演进的变化。
使用限制
版本限制
目前仅支持 Iceberg sdk 1.6.1 兼容feature。
目前仅支持 Iceberg table format v2 数据读写。
支持操作
暂不支持操作
MaxCompute管理的Iceberg表
不支持改表名语句。
不支持XCOPY跨地域复制 语句。
不支持CLONE TABLE 语句。
不支持表快照(Snapshot)语句。
不支持设置字段默认值。
不支持物化视图操作。
不支持行级访问控制。
不支持TRUNCATE。
不支持CDC(邀测)。
不支持跨地域灾备。
不支持本地备份。
不支持 CREATE OR REPLACE 语句。
不支持 LOAD 和 UNLOAD 命令。
通过控制台或 API 查询时,MaxCompute管理的Iceberg表会显示 0 字节的存储大小。