Apache Iceberg 支持 Apache Flink 的 DataStream API 和 Table API。
功能支持 | Flink | 注意事项 |
---|---|---|
SQL create catalog | ✔️ | |
SQL create database | ✔️ | |
SQL create table | ✔️ | |
SQL create table like | ✔️ | |
SQL alter table | ✔️ | 仅支持更改表属性,不支持列和分区更改 |
SQL drop_table | ✔️ | |
SQL select | ✔️ | 支持流式和批处理模式 |
SQL insert into | ✔️ | 支持流式和批处理模式 |
SQL insert overwrite | ✔️ | |
DataStream read | ✔️ | |
DataStream append | ✔️ | |
DataStream overwrite | ✔️ | |
Metadata tables | ✔️ | |
Rewrite files action | ✔️ |
在 Flink 中创建 Iceberg 表,建议使用 Flink SQL Client,这样用户更容易理解概念。
从 Apache 下载页面下载 Flink。 Iceberg 在编译 Apache Iceberg-flink-runtime jar 时使用 Scala 2.12,因此建议使用与 Scala 2.12 捆绑在一起的 Flink 1.16。
FLINK_VERSION=1.16.1
SCALA_VERSION=2.12
APACHE_FLINK_URL=https://archive.apache.org/dist/flink/
wget ${APACHE_FLINK_URL}/flink-${FLINK_VERSION}/flink-${FLINK_VERSION}-bin-scala_${SCALA_VERSION}.tgz
tar xzvf flink-${FLINK_VERSION}-bin-scala_${SCALA_VERSION}.tgz
在 Hadoop 环境中启动独立的 Flink 集群:
# HADOOP_HOME is your hadoop root directory after unpack the binary package.
APACHE_HADOOP_URL=https://archive.apache.org/dist/hadoop/
HADOOP_VERSION=2.8.5
wget ${APACHE_HADOOP_URL}/common/hadoop-${HADOOP_VERSION}/hadoop-${HADOOP_VERSION}.tar.gz
tar xzvf hadoop-${HADOOP_VERSION}.tar.gz
HADOOP_HOME=`pwd`/hadoop-${HADOOP_VERSION}
export HADOOP_CLASSPATH=`$HADOOP_HOME/bin/hadoop classpath`
# Start the flink standalone cluster
./bin/start-cluster.sh
启动 Flink SQL 客户端。 Iceberg项目中有一个单独的flink-runtime模块来生成捆绑的jar,可以直接由Flink SQL客户端加载。要手动构建 flink-runtime 捆绑的 jar,请构建 Iceberg 项目,它将在
# HADOOP_HOME is your hadoop root directory after unpack the binary package.
export HADOOP_CLASSPATH=`$HADOOP_HOME/bin/hadoop classpath`
./bin/sql-client.sh embedded -j <flink-runtime-directory>/iceberg-flink-runtime-1.16-1.3.0.jar shell
默认情况下,Iceberg 附带用于 Hadoop 目录的 Hadoop jar。要使用 Hive 目录,请在打开 Flink SQL 客户端时加载 Hive jar。幸运的是,Flink 为 SQL 客户端提供了捆绑的 Hive jar。有关如何下载依赖项并开始使用的示例:
# HADOOP_HOME is your hadoop root directory after unpack the binary package.
export HADOOP_CLASSPATH=`$HADOOP_HOME/bin/hadoop classpath`
ICEBERG_VERSION=1.3.0
MAVEN_URL=https://repo1.maven.org/maven2
ICEBERG_MAVEN_URL=${MAVEN_URL}/org/apache/iceberg
ICEBERG_PACKAGE=iceberg-flink-runtime
wget ${ICEBERG_MAVEN_URL}/${ICEBERG_PACKAGE}-${FLINK_VERSION_MAJOR}/${ICEBERG_VERSION}/${ICEBERG_PACKAGE}-${FLINK_VERSION_MAJOR}-${ICEBERG_VERSION}.jar -P lib/
HIVE_VERSION=2.3.9
SCALA_VERSION=2.12
FLINK_VERSION=1.16.1
FLINK_CONNECTOR_URL=${MAVEN_URL}/org/apache/flink
FLINK_CONNECTOR_PACKAGE=flink-sql-connector-hive
wget ${FLINK_CONNECTOR_URL}/${FLINK_CONNECTOR_PACKAGE}-${HIVE_VERSION}_${SCALA_VERSION}/${FLINK_VERSION}/${FLINK_CONNECTOR_PACKAGE}-${HIVE_VERSION}_${SCALA_VERSION}-${FLINK_VERSION}.jar
./bin/sql-client.sh embedded shell
使用 pip 安装 Apache Flink 依赖项:
pip install apache-flink==1.16.1
提供iceberg-flink-runtime jar的file://路径,可以通过构建项目并查看/flink-runtime/build/libs获得,或者从Apache官方下载存储库。第三方 jar 可以通过以下方式添加到 pyflink:
官方文档中也提到了这一点。下面的示例使用 env.add_jars(…):
import os
from pyflink.datastream import StreamExecutionEnvironment
env = StreamExecutionEnvironment.get_execution_environment()
iceberg_flink_runtime_jar = os.path.join(os.getcwd(), "iceberg-flink-runtime-1.16-1.3.0.jar")
env.add_jars("file://{}".format(iceberg_flink_runtime_jar))
接下来,创建StreamTableEnvironment并执行Flink SQL语句。以下示例展示了如何通过 Python Table API 创建自定义目录:
from pyflink.table import StreamTableEnvironment
table_env = StreamTableEnvironment.create(env)
table_env.execute_sql("""
CREATE CATALOG my_catalog WITH (
'type'='iceberg',
'catalog-impl'='com.my.custom.CatalogImpl',
'my-additional-catalog-config'='my-value'
)
""")
运行查询:
(table_env
.sql_query("SELECT PULocationID, DOLocationID, passenger_count FROM my_catalog.nyc.taxis LIMIT 5")
.execute()
.print())
+----+----------------------+----------------------+--------------------------------+
| op | PULocationID | DOLocationID | passenger_count |
+----+----------------------+----------------------+--------------------------------+
| +I | 249 | 48 | 1.0 |
| +I | 132 | 233 | 1.0 |
| +I | 164 | 107 | 1.0 |
| +I | 90 | 229 | 1.0 |
| +I | 137 | 249 | 1.0 |
+----+----------------------+----------------------+--------------------------------+
5 rows in set
Flink 支持使用 Flink SQL 创建目录。
目录配置
通过执行以下查询来创建和命名目录(将
CREATE CATALOG <catalog_name> WITH (
'type'='iceberg',
`` =``
);
以下属性可以全局设置,并且不限于特定的目录实现:
这将创建一个名为 hive_catalog 的 Iceberg 目录,可以使用 ‘catalog-type’=‘hive’ 进行配置,该目录从 Hive 元存储加载表:
CREATE CATALOG hive_catalog WITH (
'type'='iceberg',
'catalog-type'='hive',
'uri'='thrift://localhost:9083',
'clients'='5',
'property-version'='1',
'warehouse'='hdfs://nn:8020/warehouse/path'
);
如果使用 Hive 目录,可以设置以下属性:
创建表
CREATE TABLE `hive_catalog`.`default`.`sample` (
id BIGINT COMMENT 'unique id',
data STRING
);
写数据
要将新数据附加到具有 Flink 流作业的表中,请使用 INSERT INTO:
INSERT INTO `hive_catalog`.`default`.`sample` VALUES (1, 'a');
INSERT INTO `hive_catalog`.`default`.`sample` SELECT id, data from other_kafka_table;
要将表中的数据替换为查询结果,请在批处理作业中使用 INSERT OVERWRITE(flink 流作业不支持 INSERT OVERWRITE)。覆盖是 Iceberg 表的原子操作。
具有 SELECT 查询生成的行的分区将被替换,例如:
INSERT OVERWRITE `hive_catalog`.`default`.`sample` VALUES (1, 'a');
Iceberg 还支持通过选择值覆盖给定分区:
INSERT OVERWRITE `hive_catalog`.`default`.`sample` PARTITION(data='a') SELECT 6;
Flink 原生支持将 DataStream 和 DataStream 写入iceberg表。
StreamExecutionEnvironment env = ...;
DataStream<RowData> input = ... ;
Configuration hadoopConf = new Configuration();
TableLoader tableLoader = TableLoader.fromHadoopTable("hdfs://nn:8020/warehouse/path", hadoopConf);
FlinkSink.forRowData(input)
.tableLoader(tableLoader)
.append();
env.execute("Test Iceberg DataStream");
分支写入
FlinkSink 中的 toBranch API 还支持写入 Iceberg 表中的分支。
FlinkSink.forRowData(input)
.tableLoader(tableLoader)
.toBranch("audit-branch")
.append();
读
使用以下语句提交 Flink 批处理作业:
-- Execute the flink job in batch mode for current session context
SET execution.runtime-mode = batch;
SELECT * FROM `hive_catalog`.`default`.`sample`;
Iceberg 支持处理从历史快照 ID 开始的 Flink 流作业中的增量数据:
-- Submit the flink job in streaming mode for current session.
SET execution.runtime-mode = streaming;
-- Enable this switch because streaming read SQL will provide few job options in flink SQL hint options.
SET table.dynamic-table-options.enabled=true;
-- Read all the records from the iceberg current snapshot, and then read incremental data starting from that snapshot.
SELECT * FROM `hive_catalog`.`default`.`sample` /*+ OPTIONS('streaming'='true', 'monitor-interval'='1s')*/ ;
-- Read all incremental data starting from the snapshot-id '3821550127947089987' (records from this snapshot will be excluded).
SELECT * FROM `hive_catalog`.`default`.`sample` /*+ OPTIONS('streaming'='true', 'monitor-interval'='1s', 'start-snapshot-id'='3821550127947089987')*/ ;
SQL 也是检查表的推荐方法。要查看表中的所有快照,请使用快照元数据表:
SELECT * FROM `hive_catalog`.`default`.`sample`.`snapshots`
Iceberg支持Java API中的流式或批量读取:
DataStream<RowData> batch = FlinkSource.forRowData()
.env(env)
.tableLoader(tableLoader)
.streaming(false)
.build();
Iceberg 对 Flink 的集成会自动在 Flink 和 Iceberg 类型之间进行转换。当写入 Flink 不支持的类型(例如 UUID)的表时,Iceberg 将接受并转换 Flink 类型的值。
Flink 到 Iceberg
Flink 类型按照下表转换为 Iceberg 类型:
Flink | Iceberg | Notes |
---|---|---|
boolean | boolean | |
tinyint | integer | |
smallint | integer | |
integer | integer | |
bigint | long | |
float | float | |
double | double | |
char | string | |
varchar | string | |
string | string | |
binary | binary | |
varbinary | fixed | |
decimal | decimal | |
date | date | |
time | time | |
timestamp | timestamp without timezone | |
timestamp_ltz | timestamp with timezone | |
array | list | |
map | map | |
multiset | map | |
row | struct | |
raw | Not supported | |
interval | Not supported | |
structured | Not supported | |
timestamp with zone | Not supported | |
distinct | Not supported | |
null | Not supported | |
symbol | Not supported | |
logical | Not supported |
Iceberg to Flink
Iceberg 类型按照下表转换为 Flink 类型:
Iceberg | Flink |
---|---|
boolean | boolean |
struct | row |
list | array |
map | map |
integer | integer |
long | bigint |
float | float |
double | double |
date | date |
time | time |
timestamp without timezone | timestamp(6) |
timestamp with timezone | timestamp_ltz(6) |
string | varchar(2147483647) |
uuid | binary(16) |
fixed(N) | binary(N) |
binary | varbinary(2147483647) |
decimal(P, S) | decimal(P, S) |
目前的 Flink Iceberg 集成工作尚不支持一些功能: