跳到主要内容

Apache Iceberg™ 表

Introduced or updated: v1.2.725

Databend 支持集成 Apache Iceberg™ catalog,增强了数据管理和分析的兼容性与灵活性。通过将 Apache Iceberg™ 强大的元数据和存储管理能力无缝融入平台,进一步扩展了 Databend 的功能边界。

Iceberg 快速入门

如果你想快速体验 Iceberg 并在本地进行表操作实验,可以使用这个基于 Docker 的入门项目。该环境支持:

  • 运行带 Iceberg 支持的 Spark
  • 使用 REST catalog(Iceberg REST Fixture)
  • 通过 MinIO 模拟 S3 兼容的对象存储
  • 将 TPC-H 示例数据加载到 Iceberg 表中进行查询测试

前置条件

开始前,请确保系统已安装 Docker 和 Docker Compose。

启动 Iceberg 环境

git clone https://github.com/databendlabs/iceberg-quick-start.git
cd iceberg-quick-start
docker compose up -d

该命令会启动以下服务:

  • spark-iceberg:带 Iceberg 的 Spark 3.4
  • rest:Iceberg REST Catalog
  • minio:S3 兼容的对象存储
  • mc:MinIO 客户端(用于初始化 bucket)
WARN[0000] /Users/eric/iceberg-quick-start/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion
[+] Running 5/5
✔ Network iceberg-quick-start_iceberg_net Created 0.0s
✔ Container iceberg-rest-test Started 0.4s
✔ Container minio Started 0.4s
✔ Container mc Started 0.6s
✔ Container spark-iceberg S... 0.7s

通过 Spark Shell 加载 TPC-H 数据

执行以下命令,生成并加载 TPC-H 示例数据到 Iceberg 表:

docker exec spark-iceberg bash /home/iceberg/load_tpch.sh
Collecting duckdb
Downloading duckdb-1.2.2-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl (18.7 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 18.7/18.7 MB 5.8 MB/s eta 0:00:00
Requirement already satisfied: pyspark in /opt/spark/python (3.5.5)
Collecting py4j==0.10.9.7
Downloading py4j-0.10.9.7-py2.py3-none-any.whl (200 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 200.5/200.5 kB 5.9 MB/s eta 0:00:00
Installing collected packages: py4j, duckdb
Successfully installed duckdb-1.2.2 py4j-0.10.9.7

[notice] A new release of pip is available: 23.0.1 -> 25.1.1
[notice] To update, run: pip install --upgrade pip
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
25/05/07 12:17:27 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
25/05/07 12:17:28 WARN Utils: Service 'SparkUI' could not bind on port 4040. Attempting port 4041.
[2025-05-07 12:17:18] [INFO] Starting TPC-H data generation and loading process
[2025-05-07 12:17:18] [INFO] Configuration: Scale Factor=1, Data Dir=/home/iceberg/data/tpch_1
[2025-05-07 12:17:18] [INFO] Generating TPC-H data with DuckDB (Scale Factor: 1)
[2025-05-07 12:17:27] [INFO] Generated 8 Parquet files in /home/iceberg/data/tpch_1
[2025-05-07 12:17:28] [INFO] Loading data into Iceberg catalog
[2025-05-07 12:17:33] [INFO] Created Iceberg table: demo.tpch.part from part.parquet
[2025-05-07 12:17:33] [INFO] Created Iceberg table: demo.tpch.region from region.parquet
[2025-05-07 12:17:33] [INFO] Created Iceberg table: demo.tpch.supplier from supplier.parquet
[2025-05-07 12:17:35] [INFO] Created Iceberg table: demo.tpch.orders from orders.parquet
[2025-05-07 12:17:35] [INFO] Created Iceberg table: demo.tpch.nation from nation.parquet
[2025-05-07 12:17:40] [INFO] Created Iceberg table: demo.tpch.lineitem from lineitem.parquet
[2025-05-07 12:17:40] [INFO] Created Iceberg table: demo.tpch.partsupp from partsupp.parquet
[2025-05-07 12:17:41] [INFO] Created Iceberg table: demo.tpch.customer from customer.parquet
+---------+---------+-----------+
|namespace|tableName|isTemporary|
+---------+---------+-----------+
| tpch| customer| false|
| tpch| lineitem| false|
| tpch| nation| false|
| tpch| orders| false|
| tpch| part| false|
| tpch| partsupp| false|
| tpch| region| false|
| tpch| supplier| false|
+---------+---------+-----------+

[2025-05-07 12:17:42] [SUCCESS] TPCH data generation and loading completed successfully

在 Databend 中查询数据

TPC-H 表加载完成后,即可在 Databend 中查询数据:

  1. 在 Docker 中启动 Databend:
docker network create iceberg_net
docker run -d \
--name databend \
--network iceberg_net \
-p 3307:3307 \
-p 8000:8000 \
-p 8124:8124 \
-p 8900:8900 \
datafuselabs/databend
  1. 先通过 BendSQL 连接 Databend,再创建 Iceberg catalog:
bendsql
Welcome to BendSQL 0.24.1-f1f7de0(2024-12-04T12:31:18.526234000Z).
Connecting to localhost:8000 as user root.
Connected to Databend Query v1.2.725-8d073f6b7a(rust-1.88.0-nightly-2025-04-21T11:49:03.577976082Z)
Loaded 1436 auto complete keywords from server.
Started web server at 127.0.0.1:8080
CREATE CATALOG iceberg TYPE = ICEBERG CONNECTION = (
TYPE = 'rest'
ADDRESS = 'http://host.docker.internal:8181'
warehouse = 's3://warehouse/wh/'
"s3.endpoint" = 'http://host.docker.internal:9000'
"s3.access-key-id" = 'admin'
"s3.secret-access-key" = 'password'
"s3.region" = 'us-east-1'
);
  1. 切换到新创建的 catalog:
USE CATALOG iceberg;
  1. 查看可用数据库:
SHOW DATABASES;
╭──────────────────────╮
│ databases_in_iceberg │
│ String │
├──────────────────────┤
│ tpch │
╰──────────────────────╯
  1. 执行示例查询,对 TPC-H 数据进行聚合:
SELECT
l_returnflag,
l_linestatus,
SUM(l_quantity) AS sum_qty,
SUM(l_extendedprice) AS sum_base_price,
SUM(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
SUM(l_extendedprice * (1 - l_discount) * (1 + l_tax)) AS sum_charge,
AVG(l_quantity) AS avg_qty,
AVG(l_extendedprice) AS avg_price,
AVG(l_discount) AS avg_disc,
COUNT(*) AS count_order
FROM
iceberg.tpch.lineitem
GROUP BY
l_returnflag,
l_linestatus
ORDER BY
l_returnflag,
l_linestatus;
┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ l_returnflag │ l_linestatus │ sum_qty │ sum_base_price │ sum_disc_price │ sum_charge │ avg_qty │ avg_price │ avg_disc │ count_order │
│ Nullable(String) │ Nullable(String) │ Nullable(Decimal(38, 2)) │ Nullable(Decimal(38, 2)) │ Nullable(Decimal(38, 4)) │ Nullable(Decimal(38, 6)) │ Nullable(Decimal(38, 8)) │ Nullable(Decimal(38, 8)) │ Nullable(Decimal(38, 8)) │ UInt64 │
├──────────────────┼──────────────────┼──────────────────────────┼──────────────────────────┼──────────────────────────┼──────────────────────────┼──────────────────────────┼──────────────────────────┼──────────────────────────┼─────────────┤
│ A │ F │ 37734107.0056586554400.7353758257134.870055909065222.82769225.5220058538273.129734620.049985301478493
│ N │ F │ 991417.001487504710.381413082168.05411469649223.19437525.5164719238284.467760850.0500934338854
│ N │ O │ 76633518.00114935210409.19109189591897.4720113561024263.01378225.5020196438248.015609060.050000263004998
│ R │ F │ 37719753.0056568041380.9053741292684.604055889619119.83193225.5057936138250.854626100.050009411478870
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

数据类型映射

下表列出了 Apache Iceberg™ 与 Databend 之间的数据类型对应关系。注意,表中未列出的 Iceberg 数据类型暂不支持。

Apache Iceberg™Databend
BOOLEANBOOLEAN
INTINT32
LONGINT64
DATEDATE
TIMESTAMP/TIMESTAMPZTIMESTAMP
FLOATFLOAT
DOUBLEDOUBLE
STRING/BINARYSTRING
DECIMALDECIMAL
ARRAY<TYPE>ARRAY,支持嵌套
MAP<KEYTYPE, VALUETYPE>MAP
STRUCT<COL1: TYPE1, COL2: TYPE2, ...>TUPLE
LISTARRAY

管理 Catalog

Databend 提供以下命令用于管理 catalog:

CREATE CATALOG

在 Databend 查询引擎中定义并创建一个新的 catalog。

语法

CREATE CATALOG <catalog_name>
TYPE=ICEBERG
CONNECTION=(
TYPE='<connection_type>'
ADDRESS='<address>'
WAREHOUSE='<warehouse_location>'
"<connection_parameter>"='<connection_parameter_value>'
"<connection_parameter>"='<connection_parameter_value>'
...
);
参数是否必填说明
<catalog_name>要创建的 catalog 名称。
TYPE指定 catalog 类型。Apache Iceberg™ 对应设置为 ICEBERG
CONNECTIONIceberg catalog 的连接参数。
TYPECONNECTION 内部)连接类型。Iceberg 通常设置为 rest,表示使用 REST 连接。
ADDRESSIceberg 服务的地址或 URL(例如 http://127.0.0.1:8181)。
WAREHOUSEIceberg warehouse 的位置,通常为 S3 bucket 或兼容的对象存储路径。
<connection_parameter>与外部存储建立连接所需的参数。具体参数因存储服务和认证方式而异,完整参数列表见下表。
连接参数说明
s3.endpointS3 endpoint 地址。
s3.access-key-idS3 access key ID。
s3.secret-access-keyS3 secret access key。
s3.session-tokenS3 session token,使用临时凭证时必填。
s3.regionS3 区域。
client.regionS3 客户端使用的区域,优先级高于 s3.region
s3.path-style-accessS3 路径风格访问。
s3.sse.typeS3 服务端加密(SSE)类型。
s3.sse.keyS3 SSE 密钥。加密类型为 kms 时为 KMS Key ID;加密类型为 custom 时为 base-64 编码的 AES256 对称密钥。
s3.sse.md5S3 SSE MD5 校验值。
client.assume-role.arn要代入的 IAM 角色 ARN,替代默认凭证链。
client.assume-role.external-id代入 IAM 角色时使用的可选外部 ID。
client.assume-role.session-name代入 IAM 角色时使用的可选会话名称。
s3.allow-anonymous是否允许匿名访问(例如公开 bucket/目录)。
s3.disable-ec2-metadata是否禁止从 EC2 metadata 加载凭证(通常与 s3.allow-anonymous 配合使用)。
s3.disable-config-load是否禁止从配置文件和环境变量加载配置。

Catalog 类型

Databend 支持四种 Iceberg catalog 类型:

  • REST Catalog

REST catalog 通过 RESTful API 与 Iceberg 表交互。

CREATE CATALOG iceberg_rest TYPE = ICEBERG CONNECTION = (
TYPE = 'rest'
ADDRESS = 'http://localhost:8181'
warehouse = 's3://warehouse/demo/'
"s3.endpoint" = 'http://localhost:9000'
"s3.access-key-id" = 'admin'
"s3.secret-access-key" = 'password'
"s3.region" = 'us-east-1'
)
  • AWS Glue Catalog

Glue catalog 的配置同时包含 Glue 服务参数和存储(S3)参数。Glue 服务参数在前,S3 存储参数(以 s3. 为前缀)在后。

CREATE CATALOG iceberg_glue TYPE = ICEBERG CONNECTION = (
TYPE = 'glue'
ADDRESS = 'http://localhost:5000'
warehouse = 's3a://warehouse/glue/'
"aws_access_key_id" = 'my_access_id'
"aws_secret_access_key" = 'my_secret_key'
"region_name" = 'us-east-1'
"s3.endpoint" = 'http://localhost:9000'
"s3.access-key-id" = 'admin'
"s3.secret-access-key" = 'password'
"s3.region" = 'us-east-1'
)
  • Storage Catalog(S3Tables Catalog)

Storage catalog 需要提供 table_bucket_arn 参数。S3Tables bucket 与普通 bucket 不同,它是由 S3Tables 管理的虚拟 bucket,无法通过 s3://{bucket_name}/{file_path} 路径直接访问,所有操作均基于 bucket ARN 进行。

Properties 参数说明:

profile_name: 使用的 AWS profile 名称。
region_name: 使用的 AWS 区域。
aws_access_key_id: AWS access key ID。
aws_secret_access_key: AWS secret access key。
aws_session_token: AWS session token。
CREATE CATALOG iceberg_storage TYPE = ICEBERG CONNECTION = (
TYPE = 'storage'
ADDRESS = 'http://localhost:9111'
"table_bucket_arn" = 'my-bucket'
-- 根据需要添加其他参数
)
  • Hive Catalog(HMS Catalog)

Hive catalog 需要提供 ADDRESS 参数(Hive metastore 地址)以及 warehouse 参数(Iceberg warehouse 位置,通常为 S3 bucket 或兼容的对象存储路径)。

CREATE CATALOG iceberg_hms TYPE = ICEBERG CONNECTION = (
TYPE = 'hive'
ADDRESS = '192.168.10.111:9083'
warehouse = 's3a://warehouse/hive/'
"s3.endpoint" = 'http://localhost:9000'
"s3.access-key-id" = 'admin'
"s3.secret-access-key" = 'password'
"s3.region" = 'us-east-1'
)

SHOW CREATE CATALOG

返回指定 catalog 的详细配置,包括类型和存储参数。

语法

SHOW CREATE CATALOG <catalog_name>;

SHOW CATALOGS

显示所有已创建的 catalog。

语法

SHOW CATALOGS [LIKE '<pattern>']

USE CATALOG

将当前会话切换到指定的 catalog。

语法

USE CATALOG <catalog_name>

Iceberg Catalog 缓存

Databend 为 Iceberg catalog 提供了专属的 Catalog Metadata Cache。首次查询 Iceberg 表时,元数据会被缓存到内存中。默认缓存有效期为 10 分钟,到期后异步刷新。这样可以避免重复获取元数据,提升 Iceberg 表的查询性能。

如需获取最新元数据,可通过以下命令手动刷新缓存:

USE CATALOG iceberg;
ALTER DATABASE tpch REFRESH CACHE; -- 刷新 tpch 数据库的元数据缓存
ALTER TABLE tpch.lineitem REFRESH CACHE; -- 刷新 lineitem 表的元数据缓存

如果不想使用元数据缓存,可在 databend-query.toml 配置文件中将 iceberg_table_meta_count 设置为 0 来完全禁用:

...
# Cache config.
[cache]
...
iceberg_table_meta_count = 0
...

除元数据缓存外,Databend 还支持对 Iceberg catalog 表进行表数据缓存,与 Fuse 表的缓存机制类似。详情请参考查询配置参考中的 cache 章节

写入 Iceberg 表

Databend 支持通过 INSERT INTO 向 Iceberg 表写入数据。可以直接使用 ENGINE = ICEBERG 子句创建 Iceberg 表,并通过 PARTITION BY 可选地定义分区列。

创建 Iceberg 表

语法

CREATE TABLE <table_name> (
<column_definitions>
) ENGINE = ICEBERG
[PARTITION BY (<column1>[, <column2>, ...])];
  • ENGINE = ICEBERG:指定表以 Iceberg 格式存储。
  • PARTITION BY:可选。定义一个或多个分区列。

支持的数据类型

以下 Databend 数据类型支持写入 Iceberg 表:

Databend 类型Iceberg 类型
BOOLEANBoolean
INTInt
BIGINTLong
FLOATFloat
DOUBLEDouble
STRINGString
DATEDate
TIMESTAMPTimestamp

插入数据

使用标准 INSERT INTO 语句向 Iceberg 表写入数据:

INSERT INTO <table_name> VALUES (...), (...);

分区表和非分区表均支持单行和多行插入。对于分区表,Databend 会自动将数据路由到对应分区。分区列中的 NULL 值同样支持。

示例

非分区表

CREATE TABLE t_scores(id INT, name STRING, score DOUBLE) ENGINE = ICEBERG;

INSERT INTO t_scores VALUES (1, 'alice', 85.5);
INSERT INTO t_scores VALUES (2, 'bob', 90.0), (3, 'charlie', 75.5);

SELECT * FROM t_scores;

┌──────────────────────────────────────────┐
│ id │ name │ score │
├────────┼──────────┼─────────────────────┤
1 │ alice │ 85.5
2 │ bob │ 90.0
3 │ charlie │ 75.5
└──────────────────────────────────────────┘

单字段分区表

CREATE TABLE t_partitioned(id INT, category STRING, amount DOUBLE)
ENGINE = ICEBERG
PARTITION BY (category);

INSERT INTO t_partitioned VALUES (1, 'A', 100.5);
INSERT INTO t_partitioned VALUES (2, 'B', 200.0), (3, 'A', 150.5), (4, 'C', 400.0);

SELECT * FROM t_partitioned;

┌──────────────────────────────────────────────┐
│ id │ category │ amount │
├────────┼────────────┼────────────────────────┤
1 │ A │ 100.5
3 │ A │ 150.5
2 │ B │ 200.0
4 │ C │ 400.0
└──────────────────────────────────────────────┘

多字段分区表

CREATE TABLE t_multi_part(id INT, region STRING, year INT, amount DOUBLE)
ENGINE = ICEBERG
PARTITION BY (region, year);

INSERT INTO t_multi_part VALUES
(1, 'US', 2023, 100.5),
(2, 'EU', 2023, 200.5),
(3, 'US', 2024, 300.5),
(4, 'EU', 2024, 400.5);

-- 向已有分区插入数据
INSERT INTO t_multi_part VALUES
(5, 'US', 2023, 500.5);

-- 分区列支持 NULL 值
INSERT INTO t_multi_part VALUES
(6, NULL, 2023, 600.5),
(7, 'US', NULL, 700.5);

SELECT * FROM t_multi_part;

┌──────────────────────────────────────────────────────┐
│ id │ region │ year │ amount │
├────────┼──────────┼──────────┼───────────────────────┤
1 │ US │ 2023100.5
5 │ US │ 2023500.5
3 │ US │ 2024300.5
2 │ EU │ 2023200.5
4 │ EU │ 2024400.5
6NULL2023600.5
7 │ US │ NULL700.5
└──────────────────────────────────────────────────────┘

Apache Iceberg™ 表函数

Databend 提供以下表函数用于查询 Iceberg 元数据,方便用户高效检查 snapshot 和 manifest:

使用示例

以下示例展示如何通过 REST 连接创建 Iceberg catalog,指定服务地址、warehouse 位置(S3)以及 AWS 区域、自定义 endpoint 等可选参数:

CREATE CATALOG ctl
TYPE=ICEBERG
CONNECTION=(
TYPE='rest'
ADDRESS='http://127.0.0.1:8181'
WAREHOUSE='s3://iceberg-tpch'
"s3.region"='us-east-1'
"s3.endpoint"='http://127.0.0.1:9000'
);
欢迎体验 Databend Cloud

基于 Rust + 对象存储构建的新一代多模态数仓,一个平台即可进行 BI、向量、全文检索及地理空间分析。

支持标准 SQL,自动弹性伸缩,助您快速构建现代化数据平台。

注册即领 ¥200 代金券。

注册体验