跳转到主要内容
为存储在 Amazon S3、Azure、HDFS 或本地的 Apache Iceberg 表提供只读的表式接口。

语法

参数

这些参数的说明分别与表函数 s3azureBlobStorageHDFSfile 中对应参数的说明一致。 format 表示 Iceberg 表中数据文件的格式。 对于 icebergS3,可使用可选参数 extra_credentials 传入 role_arn,以便在 ClickHouse Cloud 中实现基于角色的访问。有关配置步骤,请参见 安全访问 S3

返回值

一个具有指定结构的表,用于读取指定 Iceberg 表中的数据。

示例

ClickHouse 当前支持通过 icebergS3icebergAzureicebergHDFSicebergLocal 表函数,以及 IcebergS3icebergAzureIcebergHDFSIcebergLocal 表引擎,读取 Iceberg 格式的 v1 和 v2 版本。

定义命名集合

下面是一个用于存储 URL 和凭据的命名集合配置示例:

使用数据目录

Iceberg 表也可以配合多种数据目录使用,例如 REST CatalogAWS Glue Data CatalogUnity Catalog
使用目录时,大多数用户通常会选择 DataLakeCatalog 数据库引擎,它可将 ClickHouse 连接到你的目录,以发现其中的表。你可以使用此数据库引擎,而不必通过 IcebergS3 表引擎手动逐个创建表。
要使用这些目录,请使用 IcebergS3 引擎创建表,并提供必要的设置。 例如,结合 MinIO 存储使用 REST Catalog:
或者,使用 AWS Glue Data Catalog 和 S3:

Schema 演进

目前,借助 CH,你可以读取 schema 会随时间演变的 Iceberg 表。当前支持读取以下这类表:列被添加或删除,以及列顺序发生变化。你还可以将某一列从必须有值改为允许 NULL。此外,我们还支持简单类型之间允许的类型转换,即:  
  • int -> long
  • float -> double
  • decimal(P, S) -> decimal(P’, S) where P’ > P.
目前,尚不支持更改嵌套结构,或更改数组和 Map 中元素的类型。

分区裁剪

ClickHouse 支持在对 Iceberg 表执行 SELECT 查询时进行分区裁剪,这有助于通过跳过不相关的数据文件来优化查询性能。要启用分区裁剪,请设置 use_iceberg_partition_pruning = 1。有关 Iceberg 分区裁剪的更多信息,请参见 https://iceberg.apache.org/spec/#partitioning

时间旅行

ClickHouse 支持 Iceberg 表的时间旅行功能,让您可以使用特定的时间戳或快照 ID 查询历史数据。

处理含已删除行的表

目前,仅支持带有位置删除的 Iceberg 表。 以下删除方法暂不支持

基本用法

注意:不能在同一查询中同时指定 iceberg_timestamp_msiceberg_snapshot_id 参数。

重要注意事项

  • 快照通常会在以下情况下创建:
  • 向表中写入新数据时
  • 执行某种数据合并整理时
  • schema 变更通常不会创建快照——这会在对经历过 schema 演进的表使用时间旅行时带来一些重要行为。

示例场景

以下所有场景均使用 Spark,因为 CH 目前尚不支持向 Iceberg 表写入数据。

场景 1:无新增快照时的 schema 变更

考虑以下操作顺序:
不同时间戳下的查询结果:
  • 在 ts1 和 ts2:仅显示最初的两列
  • 在 ts3:显示全部三列,其中第一行的 price 为 NULL

场景 2:历史 schema 与当前 schema 的差异

在当前时刻执行时间旅行查询时,显示的 schema 可能与当前表的 schema 不同:
出现这种情况,是因为 ALTER TABLE 不会创建新的 快照;对于当前表,Spark 读取的是最新元数据文件中的 schema_id 值,而不是从某个 快照 中获取。

场景 3:历史 schema 与当前 schema 的差异

第二点是,进行时间旅行时,你无法获取表在写入任何数据之前的状态:
在 ClickHouse 中,这种行为与 Spark 保持一致。你可以直接将 Spark 的 Select 查询理解为 ClickHouse 的 Select 查询,两者的工作方式相同。

元数据文件定位

在 ClickHouse 中使用 iceberg 表函数时,系统需要找到正确的 metadata.json 文件,该文件用于描述 Iceberg 表的结构。下面介绍这一定位过程的工作方式:
  1. 直接指定路径: *如果设置了 iceberg_metadata_file_path,系统会将其与 Iceberg 表目录路径拼接,使用该精确路径。
  • 提供此设置后,所有其他解析设置都会被忽略。
  1. 表 UUID 匹配: *如果指定了 iceberg_metadata_table_uuid,系统将: *仅查看 metadata 目录中的 .metadata.json 文件 *筛选出包含 table-uuid 字段且与指定 UUID 匹配的文件 (不区分大小写)
  2. 默认搜索: *如果以上两个设置都未提供,metadata 目录中的所有 .metadata.json 文件都会成为候选项

选择最新文件

根据上述规则识别出候选文件后,系统会进一步确定其中哪个是最新的:
  • 如果启用了 iceberg_recent_metadata_file_by_last_updated_ms_field
  • 选择 last-updated-ms 值最大的文件
  • 否则:
  • 选择版本号最高的文件
  • (对于格式为 V.metadata.jsonV-uuid.metadata.json 的文件名,版本号显示为 V)
注意:上述所有设置都是表函数设置 (不是全局设置,也不是查询级设置) ,必须按如下所示指定:
注意:虽然 Iceberg 目录通常负责处理元数据解析,但 ClickHouse 中的 iceberg 表函数 会直接将存储在 S3 中的文件识别为 Iceberg 表,因此理解这些解析规则很重要。

元数据缓存

Iceberg 表引擎和表函数支持元数据缓存,可存储 manifest 文件、manifest 列表以及元数据 json 的相关信息。该缓存存储在内存中。此功能由设置 use_iceberg_metadata_files_cache 控制,且默认启用。

别名

表函数 iceberg 现为 icebergS3 的别名。

虚拟列

  • _path — 文件路径。类型:LowCardinality(String)
  • _file — 文件名。类型:LowCardinality(String)
  • _size — 文件大小 (单位:字节) 。类型:Nullable(UInt64)。如果文件大小未知,则值为 NULL
  • _time — 文件的最后修改时间。类型:Nullable(DateTime)。如果时间未知,则值为 NULL
  • _etag — 文件的 etag。类型:LowCardinality(String)。如果 etag 未知,则值为 NULL

写入 Iceberg 表

从 25.7 版本开始,ClickHouse 支持对用户的 Iceberg 表进行修改。 目前这还是一项 Experimental 功能,因此首先需要启用它:

创建表

要创建自己的空 Iceberg 表,请使用与读取时相同的命令,但需要显式指定 schema。 写入支持 Iceberg 规范中的所有数据格式,例如 Parquet、Avro、ORC。

示例

注意:如需创建 version hint 文件,请启用 iceberg_use_version_hint 设置。 如果要压缩 metadata.json 文件,请在 iceberg_metadata_compression_method 设置中指定编解码器名称。

INSERT

创建新表后,您可以使用标准的 ClickHouse 语法插入数据。

示例

DELETE

ClickHouse 也支持在 merge-on-read 格式下删除多余的行。 该查询会创建一个包含位置删除文件的新快照。

示例

Schema 演进

ClickHouse 允许你对简单类型 (不包括 Tuple、Array 和 Map) 的列进行添加、删除、修改或重命名。

示例

合并整理

ClickHouse 支持对 Iceberg 表执行合并整理。目前,它可以在更新元数据的同时,将位置删除文件合并到数据文件中。此前的快照 ID 和时间戳保持不变,因此仍可使用相同的值进行时间旅行查询。 使用方法:

过期快照

Iceberg 表会在每次 INSERT、DELETE 或 UPDATE 操作时累积快照。随着时间推移,这可能会产生大量快照及其关联的数据文件。expire_snapshots 命令会删除旧快照,并清理不再被任何保留快照引用的数据文件。 语法:
默认情况下,要保留哪些快照由保留策略决定 (表属性 min-snapshots-to-keepmax-snapshot-age-ms 以及针对各 ref 的覆盖配置) 。指定 snapshot_ids 时,会绕过保留策略,并且只会将列出的快照纳入过期处理范围。 参数:
  • 'timestamp' (位置参数) 或 expire_before = 'timestamp' — 一个日期时间字符串 (例如 '2024-06-01 00:00:00') ,按服务器时区解释。它相当于一个安全阀:timestamp-ms 等于或晚于该值的快照会受到保护,不会被过期处理,即使按保留策略原本应被过期处理。可与 snapshot_ids 组合使用;在这种情况下,列表中等于或晚于该时间戳的快照不会被过期处理。
  • retention_period = '<duration>' — 仅对本次调用覆盖表级 history.expire.max-snapshot-age-ms。早于该时长的快照 (从当前时刻往前计算) 会成为过期候选。该值是一个时长字符串,由一个或多个连续拼接的 {number}{unit} 对组成。支持的单位:y (365 天) 、w (7 天) 、d (24 小时) 、h (60 分钟) 、m (60 秒) 、s (1 秒) 、ms (1 毫秒) 。单位可以组合,例如 '3d''12h''1d12h30m''500ms'
  • retain_last = N — 仅对本次调用覆盖表级 history.expire.min-snapshots-to-keep。无论快照多旧,始终至少保留 N 个快照。
  • snapshot_ids = [id1, id2, ...] — 仅对列出的快照 ID 执行过期处理 (当前快照、分支或标签引用的快照除外) 。此模式会完全绕过保留策略,且不能与 retention_periodretain_last 组合使用。
  • dry_run = 1 — 计算哪些内容会被过期处理,并返回指标,但不会写入新元数据或删除文件。
retention_periodretain_last 仅覆盖表级保留默认值。Iceberg 表属性中为各 ref (branch/tag) 配置的保留覆盖 (例如 refs.<branch>.min-snapshots-to-keep) 绝不会被覆盖——它们始终按表元数据中的配置生效。
示例:
输出: 该命令会返回一个包含两列 (metric_name Stringmetric_value Int64) 的表,其中每个指标对应一行。指标名称遵循 Iceberg 规范 该命令执行以下步骤:
  1. 评估保留策略 (见下文) ,以确定必须保留哪些快照
  2. 如果提供了时间戳参数,还会额外保护该时间戳及之后的所有快照
  3. 让既未被保留策略保留、也未受时间戳保护机制保护的快照过期
  4. 计算哪些文件仅与已过期的快照关联
  5. 在正常模式下:生成不包含已过期快照的新元数据
  6. 在正常模式下:物理删除不可达的 manifest 列表、manifest 文件和数据文件
  7. dry_run = 1 模式下:跳过步骤 5 和 6,仅返回计算出的指标

快照保留策略

expire_snapshots 命令遵循 Iceberg 快照保留策略。保留策略通过 Iceberg 表属性以及按引用的覆盖设置进行配置: 每个快照引用 (Iceberg 元数据中的 refs) 都可以通过引用级字段覆盖这些值:min-snapshots-to-keepmax-snapshot-age-msmax-ref-age-ms 保留规则评估:
  • 对于每个分支 (包括 main) :从分支头开始遍历其祖先链。只要满足以下任一条件,就会保留该快照:
    • 该快照位于祖先链中的前 min-snapshots-to-keep 个快照之内
    • 该快照的存在时长未超过 max-snapshot-age-ms (即 now - timestamp-ms <= max-snapshot-age-ms)
  • 对于标签:被标记的快照会被保留,除非该标签已超过其 max-ref-age-ms,此时会移除该标签引用
  • main 引用 如果其存在时长超过 max-ref-age-ms,将被完全移除 (main 分支永远不会被移除)
  • 悬空引用 如果指向不存在的快照,将在发出警告后被移除
  • 当前快照始终会被保留,无论保留设置如何
所需权限: 需要 ALTER TABLE EXECUTE 权限,它在 ClickHouse 访问控制层级中是 ALTER TABLE 的子权限。你可以单独授予该权限,也可以通过其父权限授予:
  • 仅支持 Iceberg format version 2 表 (v1 快照不保证包含 manifest-list,而安全识别待清理文件需要它)
  • 当前快照始终会被保留,即使它早于指定的 timestamp
  • 要求启用 allow_insert_into_iceberg 设置
  • 要求启用 allow_experimental_expire_snapshots 设置
  • 当 ClickHouse 更新元数据时,目录 自身的授权 (REST catalog auth、AWS Glue IAM 等) 仍会独立执行

删除孤立文件

孤立文件是指存储中存在、但未被 Iceberg 表元数据中的任何快照引用的文件。它们会因写入失败、合并整理后的清理不完整以及操作中断而不断累积,导致存储空间持续增长且无上限。remove_orphan_files 命令可用于识别并删除这些孤立文件。 语法:
参数: 示例:
输出: 该命令会返回一个表,包含 metric_namemetric_value 两列,按类别显示已删除文件的数量 (或在 dry_run 模式下将要删除的文件数量) 。文件类别会基于文件命名约定,采用尽力而为的启发式规则进行分类;不匹配任何特定模式的文件默认计入 deleted_data_files_count 设置:
  • 需要 Iceberg format version 2 (或更高版本) 。 Version 1 表会被拒绝,因为其快照中缺少 manifest-list 指针,而安全确定可达文件集合需要这些指针。在 v1 表上运行该命令会返回 BAD_ARGUMENTS 错误。
  • 需要同时启用 allow_insert_into_icebergallow_iceberg_remove_orphan_files 设置
  • 建议先运行 expire_snapshots,再运行 remove_orphan_files,以便先清理由已过期快照唯一引用的文件
  • 使用 dry_run = 1 可在删除前预览孤儿文件
  • older_than 阈值可防止删除仍在写入中的文件——默认 3 天的阈值提供了较为充足的安全余量

另请参见

最后修改于 2026年7月2日