关于数据库:创建Iceberg表的步骤DEEPNOVA开发者社区

3次阅读

共计 3383 个字符,预计需要花费 9 分钟才能阅读完成。

作者:闻乃松

创立表是引擎的必备根本能力,引擎有很多,Hive、Spark、Flink、Trino 等等,咱们权且只关注这些,创立的表依照是否跟引擎绑定,分为两大类:managed table 和 external table。以这里举例的引擎为例,它们都能够将表元数据保护在 Hive Metastore 中,对引擎来讲,这些表以 external table 的模式存在。

在本文中,咱们将话题限度在 Hive、Spark、Flink、Trino 如何创立 Iceberg 表,并且保障各引擎都能够无障碍相互拜访。这样,咱们的话题分为 3 个局部:

  1. 不同引擎创立的 Iceberg 表为什么不兼容?
  2. 如何屏蔽不同引擎创立 Iceberg 表的差别?
  3. 创立独立引擎的 Iceberg 表的步骤

不同引擎创立的 Iceberg 表为什么不兼容

Hive、Spark、Flink、Trino 创立的 Iceberg 表元数据都存储在 HMS 中,也就是复用了 HMS 的存储模型,次要波及的表的互相关系如下:

以 Hive 创立的 Iceberg 表为例,来看看其存储内容:

CREATE TABLE default.sample_hive_table_1(id bigint, name string) PARTITIONED BY(dept string) STORED BY ‘org.apache.iceberg.mr.hive.HiveIcebergStorageHandler’;

首先在 TBLS 中存储了一条记录:记录了以后表的 ID,名称,类型,数据库 ID,序列化 ID,拥有者等信息。在 TABLE_PARAMS 中存储了相干参数:

storage_handler 记录了以后表须要用 Iceberg handler 来解决。Iceberg 表的元数据信息,通过 metadata_location 和 previous_metadata_location 指定,前者代表最新变更记录,后者代表上一次的变更记录。

在字段表 COLUMNS_V2 中记录了字段信息:

由图可知,其并没有存储分区字段,分区信息存储在元数据文件中。这个表只保留表最新版本的字段信息。

SERDES 和 SERDES_PARAMS 存储序列化相干的信息,重要的字段只有一个:SERDES.SLIB=org.apache.iceberg.mr.hive.HiveIcebergSerDe

如果你用其余引擎来创立 Iceberg 表,会发现元数据存储上的几个差异:

首先是序列化信息变成了:

SERDES.SLIB=org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe

其次是 SDS 的存储格局变成了其余 HDFS 文件格式(以下为示例格局):

最初是没有 Iceberg 的 storage_handler 属性,因为这些格局跟 Hive 创立的 Iceberg 表的差别,导致 Hive 引擎无奈辨认其余引擎创立的表,而其余几种引擎之间是互通的,且能拜访 Hive 创立的 Iceberg 表,互通关系体现为:

其中红色箭头示意单项互通。

如何屏蔽不同引擎创立 Iceberg 表的差别

最简略的方法是间接批改元数据:

NSERT INTO TABLE_PARAMS (TBL_ID, PARAM_KEY, PARAM_VALUE) 
    VALUES(898, 'storage_handler', 'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler'); 

update SDS set INPUT_FORMAT =NULL ,OUTPUT_FORMAT =NULL where SD_ID =898;

update SERDES set slib='org.apache.iceberg.mr.hive.HiveIcebergSerDe' 
    where serde_ID =898

为了做到 Iceberg 表元数据的真正中立,也能够将 SDS 的 INPUT_FORMAT 和 OUTPUT_FORMAT 字段都置 NULL。

这是通过预先修补的方法来做到的,是否在创立表之前就批改呢?并且不批改各引擎的实现代码。实际上,引擎创立 Iceberg 表,是通过 iceberg API 来实现的,交互逻辑大略是这个样子:

那是不是有方法间接通过 Iceberg API 创立 HMS 表呢?of course!

更进一步,咱们将上述逻辑模型,形象成如下构造,引擎变成了通用了 Restful API,现实状况下,应用方只须要传入创立表的相干参数等信息即可:

这样一来,不论是 Hive 表还是 Iceberg 表,都能够通过这个模型实现表的创立。接下来,咱们看如何形象这样的表模型。

创立独立引擎的 Iceberg 表的步骤

通过下面元数据的剖析,能够将创立 Iceberg 表的元数据信息分为上面几类:

表名称和类型信息,用一个复合字段来示意:

"name": { 
    "catalogName": "mycatalog",
    "databaseName": "test_iceberg_db", 
    "tableName": "test_iceberg_table", 
    "type": "TABLE"
}

域字段列表信息,用一个复合数组示意:

"fields": [ 
    { 
    "comment": "primary key", 
    "defaultValue": 0,
    "isIndexKey": true, 
    "isNullable": false, 
    "isSortKey": true, 
    "name": "id", 
    "type": "int" 
    }, 
    { 
    "comment": "data value",
    "defaultValue": "","isIndexKey": false,"isNullable": false,"isSortKey": false,"name":"data","source_type":"string","type":"string" 
    }
]

元数据信息,用一个复合构造示意:

"metadata": { 
    "table_type": "ICEBERG",
    "location": "s3a://faas-ethan/warehouse/test_iceberg_db/test_iceberg_table" 
}

序列化信息,用一个复合构造示意:

"serde": { 
    "inputFormat": "org.apache.iceberg.mr.hive.HiveIcebergInputFormat", 
    "outputFormat": "org.apache.iceberg.mr.hive.HiveIcebergOutputFormat", 
    "parameters": 
    {"k1":"v1"}, 
    "serializationLib": "string", 
    "uri": "your_hive_table_locaton"
}

有了表的模型之后,就能够依照上面创立 Hive 表的创立模板来走了:

// 创立 Fields 
List<FieldSchema> fields = new ArrayList<FieldSchema>();
fields.add(new FieldSchema("colname", serdeConstants.STRING_TYPE_NAME, "comment"));
// 创立 StorageDescriptor 
StorageDescriptor sd = new StorageDescriptor(); 
sd.setCols(fields); sd.setSerdeInfo(new SerDeInfo()); 
// 创立 Table 对象 
Table tbl = new Table(); 
tbl.setDbName(DB_NAME); 
tbl.setTableName(TBL_NAME);
tbl.setSd(sd); 
// 申请 HMS 长久化
Table table=hiveMetaStoreClient.createTable(tbl);

下面示例代码将创立 Hive 的模板流程划分为 4 个步骤:

  • 创立 Fields
  • 创立 StorageDescriptor
  • 创立 Table 对象
  • 申请 HMS 长久化 Table

总结

本文讲述了不同引擎,次要是 Hive、Spark、Flink 和 Trino,在创立 Iceberg 表上存在的兼容性问题及其产生的起因,而后给出了解决办法。最初,通过形象一种创立跟引擎无关的 Iceberg 表的示意办法及其创立步骤。该办法的重要作用是可能实现通用的元数据管理。

正文完
 0