作者:闻乃松

Iceberg作为一种表格局治理标准,其数据分为元数据和表数据。元数据和表数据独立存储,元数据目前反对存储在本地文件系统、HMS、Hadoop、JDBC数据库、AWS Glue和自定义存储。表数据反对本地文件系统、HDFS、S3、MinIO、OBS、OSS等。元数据存储基于HMS比拟宽泛,在这篇文章中,表数据存储基于MinIO、元数据存储次要基于HMS。实际上,基于HMS存储的元数据也只是很少的信息存储在HMS中,主体元数据还是存储在内部零碎,如HDFS、MinIO等,所以这里也不得不提基于Hadoop存储的形式。

Iceberg的元数据管理通过Catalog类型指定,咱们次要关注hive、hadoop和location_based_table这三种。

如果不指定任何Catalog类型,间接创立表会怎么样呢?

add jar /Users/deepexi/.m2/repository/org/apache/iceberg/iceberg-hive-runtime/0.13.2/iceberg-hive-runtime-0.13.2.jar;SET hive.vectorized.execution.enabled=false; CREATE TABLE default.sample_local_hive_table_1( id bigint, name string )     PARTITIONED BY( dept string )     STORED BY 'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler'; 

创立Iceberg表须要借助HiveIcebergStorageHandler来实现,此时只会在本地HMS(hive-site.xml中配置) 中存储元数据,元数据表table_params显示,以后表的存储地位应用了本地HMS (hive-site.xml中配置)的文件存储门路:

这合乎创立Hive表的惯例动作。来看看,如果指定hive的Catalog,并配置近程的HMS,会怎么样?

注册hive类型的Catalog

这里注册了一个远端的HMS地址:

SET iceberg.catalog.another_hive.type=hive; SET iceberg.catalog.another_hive.uri=thrift://10.201.0.202:49153; SET iceberg.catalog.another_hive.warehouse=s3a://faas-ethan/warehouse/; SET hive.vectorized.execution.enabled=false; 

在以后HiveCli创立Hive Iceberg 表,同时指定location 存储地位,应用下面注册的hive类型的Catalog:

 CREATE TABLE default.sample_hive_table_1( id bigint, name string )      PARTITIONED BY( dept string )      STORED BY 'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler' location 's3a://faas-ethan/warehouse/default/sample_hive_table_1'      TBLPROPERTIES ('iceberg.catalog'='another_hive'); 

到本地HMS(hive-site.xml中配置) table_params元数据表中确认以后表的存储参数:

Location信息存储在SDS表中。该表存储类型为MANAGED_TABLE。再到近程HMS(another_hive.uri指定)的元数据表table_params看存储内容:

除了本地HMS存储的信息外,还多了无关Iceberg的统计信息、元数据地位信息。Location信息也同步复制了一份,存储在SDS表中,但该表存储类型变成了EXTERNAL_TABLE。由此可见,在Hive中创立Iceberg表,会在两边HMS别离存储一份元数据,只有这样,远端HMS中的Iceberg表才对本地HMS可见,所以必须保障远端HMS存在对应的数据库。如果在以后Hive Cli查看建表语句,会失去上面的输入:

show create table sample_hive_table_1; CREATE TABLE `sample_hive_table_1`( `id` bigint COMMENT 'from deserializer',                                       `name` string COMMENT 'from deserializer',                                      `dept` string COMMENT 'from deserializer')     ROW FORMAT SERDE    'org.apache.iceberg.mr.hive.HiveIcebergSerDe'      STORED BY    'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler'      WITH SERDEPROPERTIES (    'serialization.format'='1')     LOCATION  's3a://faas-ethan/warehouse/default/sample_hive_table_1'     TBLPROPERTIES (       'bucketing_version'='2',        'external.table.purge'='TRUE',        'iceberg.catalog'='another_hive',        'table_type'='ICEBERG',        'transient_lastDdlTime'='1659949858')  Time taken: 5.45 seconds, Fetched: 18 row(s) 

这示意,Hive Cli返回的信息来自本地HMS,同一般Hive相似。

问题:如果只有远端HMS的Iceberg表,如何在本地HMS拜访?

此时能够通过如下创立external表面的模式在本地HMS生成元数据:

CREATE EXTERNAL TABLE default.sample_hive_table_1( id bigint, name string )      PARTITIONED BY( dept string )      STORED BY 'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler'      location 's3a://faas-ethan/warehouse/default/sample_hive_table_1'      TBLPROPERTIES ('iceberg.catalog'='another_hive'); 

这有什么作用?试试上面的语句:

select * from default.sample_local_hive_table_1,sample_hive_table_1; 

看到没?它通过Hive SQL实现了跨HMS的联邦查问!

注册hadoop类型的Catalog

SET iceberg.catalog.hadoop_cat.type=hadoop; SET iceberg.catalog.hadoop_cat.warehouse=s3a://faas-ethan/warehouse; 

用注册的hadoop类型的Catalog,创立hadoop Iceberg表:

CREATE TABLE default.sample_hadoop_table_1( id bigint, name string )      PARTITIONED BY ( dept string )      STORED BY 'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler'      LOCATION 's3a://faas-ethan/warehouse/default/sample_hadoop_table_1'      TBLPROPERTIES ('iceberg.catalog'='hadoop_cat'); 

如果你去看存储的元数据,会发现它跟应用hive类型的Catalog创立的表,少了metadata_location属性:

同时在MinIo中的metadata元数据文件多了version-hint.text:

这是因为两者治理以后最新元数据的版本机制不同。所以你不能基于hadoop类型的Catalog ,创立hive类型的Catalog 的Iceberg表。反过来也一样不行。

问题:以后表通过Hive Cli创立,所以会在HMS存储元数据,如果Iceberg表通过Iceberg API创立,HMS齐全没有相干信息,那如何能力拜访这种hadoop Iceberg表呢?

此时通过location指定hadoop中存储表的门路,而后通过EXTERNAL将在HMS中注册元数据,Hive会主动从中推断表Schema:

SET iceberg.catalog.hadoop_cat.type=hadoop; SET iceberg.catalog.hadoop_cat.warehouse=s3a://faas-ethan/warehouse; CREATE EXTERNAL TABLE default.sample_hadoop_table_1 STORED BY 'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler' location 's3a://faas-ethan/warehouse/default/sample_hadoop_table_1' TBLPROPERTIES ('iceberg.catalog'='hadoop_cat'); 

此时location必须合乎格局:${iceberg.catalog.hadoop_cat.warehouse}/${dbName}/${tableName},否则无奈辨认存储格局。

上述创立表面的形式也能够应用上面的形式实现:

 CREATE EXTERNAL TABLE default.sample_hadoop_table_1  STORED BY 'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler'  location 's3a://faas-ethan/warehouse/default/sample_hadoop_table_1'  TBLPROPERTIES ('iceberg.catalog'='location_based_table'); 

小 结

应用Hive SQL 创立 Iceberg表,你能够基于hive、hadoop和location_based_table类型的catalog创立Iceberg表,其中location_based_table能够看做hadoop类型的简化模式,并将内部HMS中的表通过表面的模式注册到以后HMS,从而实现Hive 的联邦查问,然而hive和hadoop类型的表在版本治理上略有不同,所以只能在同类型的catalog表上映射表面。另外,因为Hive 版本跨度较大,存在较多的不同版本的HMS兼容性问题,如HMS 3.x无奈读取HMS 2.x的元数据等。