跳到主要内容

Iceberg Catalog

概述

Iceberg是数据湖仓中广泛支持的表格式。 本RFC描述了iceberg外部目录的行为以及我们将如何实现它。

动机

Apache Iceberg 是一种广泛用于数据湖仓的表格式,它提供了更完整的逻辑数据库视图,并且在作为外部表访问时具有更高的性能,因为用户不需要了解分区,并且在访问时通过文件的索引较少,相比Hive

Iceberg的分裂和结构化也使得数据源的并发访问和版本管理更加安全、节省和方便。

Apache Iceberg的堆栈

支持Iceberg将使databend成为一个开放的数据湖,赋予其更多的OLAP能力。

指南级解释

创建Iceberg Catalog

要使用Iceberg目录,用户需要建立一个具有必要权限的iceberg存储。然后他们可以在其上创建一个catalog

CREATE CATALOG my_iceberg
TYPE="iceberg"
URL='s3://path/to/iceberg'
CONNECTION=(
ACCESS_KEY_ID=...
SECRET_ACCESS_KEY=...
...
)

访问Iceberg表的内容

SELECT * FROM my_iceberg.iceberg_db.iceberg_tbl;

在普通表和Iceberg表上的联合查询:

SELECT normal_tbl.book_name,
my_iceberg.iceberg_db.iceberg_tbl.author
FROM normal_tbl,
iceberg_tbl
WHERE normal_tbl.isbn = my_iceberg.iceberg_db.iceberg_tbl.isbn
AND iceberg_tbl.sales > 100000;

在操作表时,所有数据仍然保留在用户提供的端。

时间回溯

Iceberg提供了一系列快照及其时间戳。在其上进行时间回溯是自然的。

SELECT ...
FROM <iceberg_catalog>.<database_name>.<table_name>
AT ( { SNAPSHOT => <snapshot_id> | TIMESTAMP => <timestamp> } );

访问快照元数据

用户应该能够在目录中查找快照ID列表:

SELECT snapshot_id FROM ICEBERG_SNAPSHOT(my_iceberg.iceberg_db.iceberg_tbl);
     snapshot_id
---------------------
1234567890123456789
1234567890123456790
(2 rows)

外部表当前读取的快照ID将始终是最新的。但用户可以使用AT进行时间回溯。

参考级解释

一个新的目录类型ICEBERG,以及用于从Iceberg存储读取数据的表引擎。

表引擎

该表引擎使用户能够从已建立的Apache Iceberg端点读取数据。外部表的所有表内容和元数据应保留在用户提供的Iceberg数据源中,以Iceberg的方式。

该引擎将跟踪最后提交的快照,并且应该能够从前快照读取。

外部位置

无论Iceberg在哪里,如S3、GCS或OSS,如果Databend支持该存储,那么Iceberg应该是可访问的。用户需要告诉databend Iceberg存储的位置以及databend应该如何访问该存储。

类型约定

Iceberg说明Databend
boolean真或假BOOLEAN
int32位有符号整数INT32
long64位有符号整数INT64
float32位IEEE 754浮点数FLOAT
double64位IEEE 754浮点数DOUBLE
decimal(P, S)固定点小数;精度P,比例S不支持
date没有时区或时间的日历日期DATE
time没有日期、时区的时间戳TIMESTAMP,将日期转换为今天
timestamp没有时区的时间戳TIMESTAMP,将时区转换为GMT
timestamptz带时区的时间戳TIMESTAMP
stringUTF-8字符串VARCHAR
uuid16字节固定字节数组,通用唯一标识符VARCHAR
fixed(L)长度为L的固定长度字节数组VARCHAR
binary任意长度的字节数组VARCHAR
struct类型化值的元组OBJECT
list具有某些元素类型的值的集合ARRAY
mapOBJECT

缺点

基本原理和替代方案

Iceberg外部表

从Iceberg存储创建外部表:

CREATE EXTERNAL TABLE [IF NOT EXISTS] [db.]table_name
[(
<column_name> <data_type> [ NOT NULL | NULL] [ { DEFAULT <expr> }],
<column_name> <data_type> [ NOT NULL | NULL] [ { DEFAULT <expr> }],
...
)] ENGINE=ICEBERG
ENGINE_OPTIONS=(
DATABASE='db0'
TABLE='tbl0'
LOCATION=<external-location>
)

将引入一个新的表引擎ICEBERG,所有数据将仍然保留在Iceberg存储中。外部表还应支持用户查询其快照数据和时间回溯。

SELECT snapshot_id FROM ICEBERG_SNAPSHOT('<db_name>', '<external_table_name');
 snapshot_id
--------------
73556087355608

经过讨论,选择了上述的目录方式,因为它对Iceberg功能的支持更完整,并且更符合当前Hive目录的设计。

先前技术

未解决的问题

未来的可能性

从Iceberg快照创建表

Iceberg提供了快照功能,可以从快照创建表。

CREATE TABLE [IF NOT EXISTS] [db.]table_name
(
<column_name> <data_type> [ NOT NULL | NULL] [ { DEFAULT <expr> }],
<column_name> <data_type> [ NOT NULL | NULL] [ { DEFAULT <expr> }],
...
) ENGINE = `ICEBERG`
ENGINE_OPTIONS = (
URL = 's3://path/to/iceberg'
DATABASE = <iceberg_db>
TABLE = <iceberg_tbl>
[ SNAPSHOT = { SNAPSHOT_ID => <snapshot_id> | TIMESTAMP => <timestamp> } ]
)

模式演变

外部表使用的默认Iceberg快照应始终是最新提交的快照:

SELECT snapshot_id from ICEBERG_SNAPSHOT(iceberg_catalog.iceberg_db.iceberg_tbl);
  snapshot_id
---------------
0000000000001

支持模式演变使databend能够修改Iceberg的内容。 例如,向Iceberg表插入新记录:

INSERT INTO iceberg_catalog.iceberg_db.iceberg_tbl VALUES ('datafuselabs', 'How To Be a Healthy DBA', '2022-10-14');

这将在Iceberg存储中创建一个新的快照:

SELECT snapshot_id from ICEBERG_SNAPSHOT(iceberg_catalog.iceberg_db.iceberg_tbl);
  snapshot_id
---------------
0000000000001
0000000000002