创建Iceberg表的步骤——《DEEPNOVA开发者社区》

熵桥流沙
• 阅读 1266

作者:闻乃松

创建表是引擎的必备基本能力,引擎有很多,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的存储模型,主要涉及的表的相互关系如下:

创建Iceberg表的步骤——《DEEPNOVA开发者社区》

以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中存储了相关参数:

创建Iceberg表的步骤——《DEEPNOVA开发者社区》

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

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

创建Iceberg表的步骤——《DEEPNOVA开发者社区》

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

创建Iceberg表的步骤——《DEEPNOVA开发者社区》

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

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

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

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

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

创建Iceberg表的步骤——《DEEPNOVA开发者社区》

最后是没有Iceberg的storage_handler属性,由于这些格式跟Hive创建的Iceberg表的差异,导致Hive引擎无法识别其他引擎创建的表,而其他几种引擎之间是互通的,且能访问Hive 创建的Iceberg表,互通关系表现为:

创建Iceberg表的步骤——《DEEPNOVA开发者社区》

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

如何屏蔽不同引擎创建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表的步骤——《DEEPNOVA开发者社区》

那是不是有办法直接通过Iceberg API创建HMS表呢?of course!

更进一步,我们将上述逻辑模型,抽象成如下结构,引擎变成了通用了Restful API,理想情况下,使用方只需要传入创建表的相关参数等信息即可:

创建Iceberg表的步骤——《DEEPNOVA开发者社区》

这样一来,不论是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表的表示方法及其创建步骤。该方法的重要作用是能够实现通用的元数据管理。

点赞
收藏
评论区
推荐文章
CuterCorley CuterCorley
4年前
数据库编程 MySQL 技巧与经验
1.MySQL创建数据表时设定引擎并添加外键约束创建两个数据表,在它们之间添加外键约束,然后在被添加外键的表中添加数据,发现并没有提示报错,很正常地插入了数据,说明外键没有添加成功,在SQL可视化工具里查看表的属性,并点击外部键会出现弹窗,提示是因为引擎的问题,导致不能添加外键。MySQL安装时默认用的表引擎是MyISAM,而MyISAM是不支持外键的,如
Stella981 Stella981
4年前
Flink 1.10 和 Hive 3.0 性能对比(附 Demo 演示 PPT)
如今的大数据批计算,随着Hive数仓的成熟,普遍的模式是Hivemetastore计算引擎。常见的计算引擎有HiveonMapReduce、HiveonTez、HiveonSpark、SparkintegrateHive、PrestointegrateHive,还有随着Flink1.10发布后生产可用的Flink
Stella981 Stella981
4年前
Hive内部表和外部表的区别详解
内部表&外部表未被external修饰的是内部表(managedtable),被external修饰的为外部表(externaltable);区别:内部表数据由Hive自身管理,外部表数据由HDFS管理;内部表数据存储的位置是hive.metastore.warehouse.dir(默认:/user/hive/warehouse)
Wesley13 Wesley13
4年前
MySQL表介绍
MySQLInnoDB表介绍一、索引组织表在InnoDB引擎中,表都是根据主键顺序存放的。这种存储方式称为索引组织表,在InnoDB引擎中,每张表都有逐渐。如果没有显示定义主键,则引擎会按照以下方式选择或创建主键。(1)、判断表是否有非空唯一索引,如果有,则该字段为主键。如果有多个非空唯一索引,则选择第一个定义的非空索引字段作为
Wesley13 Wesley13
4年前
MySQL索引的索引长度问题
MySQL的每个单表中所创建的索引长度是有限制的,且对不同存储引擎下的表有不同的限制。在MyISAM表中,创建组合索引时,创建的索引长度不能超过1000,注意这里索引的长度的计算是根据表字段设定的长度来标量的,例如:createtabletest(idint,name1varchar(300),name2varchar(300),nam
Stella981 Stella981
4年前
Hive使用必知必会系列
一、Hive的几种数据模型内部表(Table将数据保存到Hive自己的数据仓库目录中:/usr/hive/warehouse)外部表(ExternalTable相对于内部表,数据不在自己的数据仓库中,只保存数据的元信息)分区表
Stella981 Stella981
4年前
ClickHouse MergeTree引擎的简单介绍
1.介绍Clickhouse中最强大的表引擎当属MergeTree(合并树)引擎及该系列(MergeTree)中的其他引擎。MergeTree允许依据主键和日期创建索引,并进行实时的数据更新操作。MergeTree是ClickHouse里最为先进的表引擎。请注意不要将MergeTree跟Merge引擎混淆!!!Mer
Wesley13 Wesley13
4年前
MySQL中四种常用存储引擎的介绍
MySQL常用的四种引擎的介绍(1):MyISAM存储引擎:不支持事务、也不支持外键,优势是访问速度快,对事务完整性没有要求或者以select,insert为主的应用基本上可以用这个引擎来创建表支持3种不同的存储格式,分别是:静态表;动态表;压缩表静态表:表中的字段都是非变长字段,这样每个记录都是固定长度的,优点存储非常迅速,容易缓存,出现故障
Wesley13 Wesley13
4年前
MySQL 存储引擎(2)
首先我们带着下边三个问题来认识存储引擎存储引擎在MySQL中的作用是什么?MySQL都有哪些存储引擎SQL又与存储引擎有什么关系?存储引擎在MySQL中的作用是什么?顾名思义,存储引擎就是用于存储我们的数据的。在关系型数据库中我们一般将数据库存放在表中(Table)。我们可以把这个表理解成Excel电子表格
Wesley13 Wesley13
4年前
Mysql数据库引擎介绍
一、数据库引擎  数据库引擎是用于存储、处理和保护数据的核心服务。利用数据库引擎可控制访问权限并快速处理事务,从而满足企业内大多数需要处理大量数据的应用程序的要求。使用数据库引擎创建用于联机事务处理或联机分析处理数据的关系数据库。这包括创建用于存储数据的表和用于查看、管理和保护数据安全的数据库对象(如索引、视图和存储过程)。二、数据库引擎任
Wesley13 Wesley13
4年前
Mysql的四种引擎介绍
1、MyISAM存储引擎  不支持事务,也不支持外键,优势是访问速度快,对事务完整性没有要求或者以select、insert为主的应用基本上可以用这个引擎来创建表。支持三种不同的存储格式,分别是:静态表、动态表、压缩表。静态表:表中的字段都是非变长字段,这样每个记录都是固定长度的,优点存储非常迅速,容易缓存,出现故障容易恢复;缺点是占