关于数据库:使用Hive-SQL查询Iceberg表的正确姿势

34次阅读

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

作者:闻乃松

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 的元数据等。

正文完
 0