原作者:Sam Redai
出处:https://tabular.io/blog/java-api-part-1/
翻译:李立伟
随着Iceberg集成到越来越多的计算引擎中,有各种提供了强大功能的接口可以供你使用。本系列将介绍在没有引擎的情况下使用冰山表的底层Java API,而本文是本系列的第一篇。
无论您是使用计算引擎的开发人员、维护生产Iceberg仓库的基础设施工程师,还是使用Iceberg表的数据工程师,Iceberg java客户端都提供了有价值的功能来支撑你使用Iceberg。尝试java客户端的最简单方法是使用notebook Iceberg - An Introduction to the Iceberg Java API.ipynb
, 你可以在我们之前的一篇文章中找到它:Docker、Spark 和 Iceberg:体验 Iceberg 的最快方式。而如果你已经在本地下载了 tabulario/spark-iceberg 的docker镜像,请确保通过 docker-compose pull
获取最新版本。
Catalog 接口
Iceberg 中的 Catalog 是 Iceberg namespaces 和 table 的目录。Iceberg 内置了许多开箱即用的Catalog,比如 Hive、Glue 和 DynamoDB。在即将发布的版本中,它甚至还将包含一个基于 REST 的通用 Catalog。你甚至可以实现自己的 Catalog 来注入特定的自定义逻辑。
在本次演示中,我们将使用 Iceberg 附带的 JdbcCatalog。让我们开始吧!
加载Catalog
要加载 Catalog,首先必须构造一个 Map 集合来配置它。所需的属性因你所要使用的 Catalog 类型而异。我们使用由 Postgres 数据库支持的 JdbcCatalog,因此我们的 Map 里需要包括 Postgres 连接信息。
所有 Catalog 通常都需要的两个属性:仓库地址(warehouse location)和 File-IO 实例。本次我们将使用一个本地目录作为仓库地址,使用 HadoopFileIO 作为 Catalog 的 File-IO 实例。
Note:要了解更多关于 Iceberg 中File-IO
的概念,请查看我们早期的一篇文章,它提供了出色的描述:Iceberg顶层设计-FileIO:云原生表
首先,让我们生成一个用于 Catalog 的 Map 集合来配置我们的 JdbcCatalog。
import org.apache.iceberg.CatalogProperties;
import org.apache.iceberg.jdbc.JdbcCatalog;
import org.apache.iceberg.hadoop.HadoopFileIO;
Map<String, String> properties = new HashMap<>();
properties.put(CatalogProperties.CATALOG_IMPL, JdbcCatalog.class.getName());
properties.put(CatalogProperties.URI, "jdbc:postgresql://postgres:5432/demo_catalog");
properties.put(JdbcCatalog.PROPERTY_PREFIX + "user", "admin");
properties.put(JdbcCatalog.PROPERTY_PREFIX + "password", "password");
properties.put(CatalogProperties.WAREHOUSE_LOCATION, "/home/iceberg/warehouse");
properties.put(CatalogProperties.FILE_IO_IMPL, HadoopFileIO.class.getName());
接下来,让我们初始化 catalog,为它设置一个名称,并传入上述包含了我们各项配置的 Map 集合。
JdbcCatalog catalog = new JdbcCatalog();
catalog.initialize("demo", properties);
好了!现在我们有了一个 catalog 实例,它包括 listing、creating、renaming 和 dropping tables 等操作。
定义表结构及分区
在下一节中,我们将创建一个表,但首先,我们必须定义表的结构。让我们创建一个具有四列的简单表结构: level, event_time, message, call_stack。
import org.apache.iceberg.Schema;
import org.apache.iceberg.types.Types;
Schema schema = new Schema(
Types.NestedField.required(1, "level", Types.StringType.get()),
Types.NestedField.required(2, "event_time", Types.TimestampType.withZone()),
Types.NestedField.required(3, "message", Types.StringType.get()),
Types.NestedField.optional(4, "call_stack", Types.ListType.ofRequired(5, Types.StringType.get()))
);
此外,让我们构建一个分区,该分区在 Event_time
列上定义一个小时的分区。
import org.apache.iceberg.PartitionSpec;
PartitionSpec spec = PartitionSpec.builderFor(schema)
.hour("event_time")
.build();
创建表
使用我们的表结构及分区,我们现在可以创建我们的表。我们将创建一个名为 “webapp”的 namespace,并在该 namespace 中创建表标识(TableIdentifier)。
import org.apache.iceberg.catalog.Namespace;
import org.apache.iceberg.catalog.TableIdentifier;
Namespace namespace = Namespace.of("webapp");
TableIdentifier name = TableIdentifier.of(namespace, "logs");
现在,让我们开始创建表!
catalog.createTable(name, schema, spec)
如果我们在 catalog 上调用 listTables 方法,我们可以在列表中看到我们新创建的表。
List<TableIdentifier> tables = catalog.listTables(namespace);
System.out.println(tables)
输出为:
[webapp.logs]
删除表
如你所料,Catalog 还包含了用于删除表的方法。让我们使用相同的表标识符删除我们在上一节中创建的表。
catalog.dropTable(name)
下一步做什么?
如果你喜欢这篇文章,请期待我们的下一篇,它将介绍查询引擎通常用于执行表扫描的核心 Java API,你也可以用它们来开发需要与 Iceberg 核心内部组件交互的程序。此外,如果你想成为 Iceberg 社区的一员,或者只是想过来打个招呼,请查看我们的社区页面,了解在哪里可以找到我们。