数据湖(五):Hudi 与 Hive 集成

本文详细介绍了如何配置HiveServer2以实现Hudi与Hive的集成,包括Hive服务端配置、Hadoop节点配置、服务重启及客户端连接。通过SparkSQL,实现了COPY_ON_WRITE和MERGE_ON_READ两种模式下数据写入Hudi并映射到Hive表的操作,同时也探讨了手动集成和使用SparkSQL操作映射的Hive表的方法。

Hudi与Hive集成

一、配置 HiveServer2

Hudi 与 Hive 集成原理是通过代码方式将数据写入到 HDFS 目录中,那么同时映射 Hive 表,让 Hive 表映射的数据对应到此路径上,这时 Hudi 需要通过 JDBC 方式连接 Hive 进行元数据操作,这时需要配置 HiveServer2。

1、在 Hive 服务端配置 hive-site.xml

#在 Hive 服务端 $HIVE_HOME/conf/hive-site.xml 中配置: hive.server2.thrift.port10000hive.server2.thrift.bind.host192.168.179.4hive.zookeeper.quorumnode3:2181,node4:2181,node5:2181

注意:“hive.zookeeper.quorum”搭建 hiveserver2HA 使用配置项,可以不配置,如果不配置启动 hiveServer2 时一直连接本地 zookeeper,导致大量错误日志(/tmp/root/hive.log),从而导致通过 beeline 连接当前 node1 节点的 hiveserver2 时不稳定,会有连接不上错误信息。

2、在每台 Hadoop 节点配置 core-site.xml,记得发送到所有节点

hadoop.proxyuser.root.hosts\*hadoop.proxyuser.root.groups\*

3、重启 HDFS ,Hive ,在 Hive 服务端启动 Metastore 和 HiveServer2 服务

[root@node1 conf]# hive --service metastore &[root@node1 conf]# hive --service hiveserver2 &

复制代码

4、在客户端通过 beeline 连接 Hive

[root@node3 test]# beelinebeeline> !connect jdbc:hive2://node1:10000 rootEnter password for jdbc:hive2://node1:10000: **** #可以输入任意密码,没有验证0: jdbc:hive2://node1:10000> show tables;

复制代码

二、代码层面集成 Hudi 与 Hive

我们可以通过 SparkSQL 将数据保存到 Hudi 中同时也映射到 Hive 表中。映射有两种模式,如果 Hudi 表是 COPY_ON_WRITE 类型,那么映射成的 Hive 表对应是指定的 Hive 表名,此表中存储着 Hudi 所有数据。

如果 Hudi 表类型是 MERGE_ON_READ 模式,那么映射的 Hive 表将会有 2 张,一张后缀为 rt ,另一张表后缀为 ro。后缀 rt 对应的 Hive 表中存储的是 Base 文件 Parquet 格式数据+log Avro 格式数据,也就是全量数据。后缀为 ro Hive 表中存储的是存储的是 Base 文件对应的数据。

1)在 pom.xml 中加入一下依赖

<**dependency**> <**groupId**>org.apache.hive</**groupId**> <**artifactId**>hive-jdbc</**artifactId**> <**version**>1.2.1</**version**> </**dependency**>

2)将对应依赖包放入 Hive 节点对应的 lib 目录下

将 hudi-hadoop-mr-bundle-0.8.0.jar、parquet-column-1.10.1.jar、parquet-common-1.10.1.jar、parquet-format-2.4.0.jar、parquet-hadoop-1.10.1.jar 包存入 Hive lib 目录下。由于 Hudi 表数据映射到 Hive 表后,Hive 表底层存储格式为“HoodieParquetInputFormat”或者“HoodieParquetRealtimeInputFormat”,解析 Parquet 数据格式时使用到以上各个包。可以从 Maven 中下载以上包后,将这些包上传到所有 Hive 节点的 lib 目录下,包括服务端和客户端。

3)启动 Hive MetaStore 与 Hive Server2 服务

[root@node1 conf]# hive --service metastore &[root@node1 conf]# hive --service hiveserver2 &

复制代码

4)将 hive-site.xml 放入项目 resources 目录中

后期 Hudi 映射 Hive 表后,会自动检查 Hive 元数据,这时需要找到配置文件连接 Hive。

1、COW 模式-SparkSQL 代码写入 Hudi 同时映射 Hive 表

1)COW 模式代码如下

//1.创建对象val session: SparkSession = SparkSession.builder().master("local").appName("insertDataToHudi")  .config("spark.serializer", "org.apache.spark.serializer.KryoSerializer")  .getOrCreate()
//2.创建DataFrameval insertDF: DataFrame = session.read.json("file:///D:\\2022IDEA_space\\SparkOperateHudi\\data\\jsondata.json")
import org.apache.spark.sql.functions._//3.向Hudi中插入数据 - COW模式insertDF  .write.format("hudi")  //设置写出模式,默认就是COW  .option(DataSourceWriteOptions.TABLE_TYPE_OPT_KEY,DataSourceWriteOptions.COW_TABLE_TYPE_OPT_VAL)  //设置主键列名称  .option(DataSourceWriteOptions.RECORDKEY_FIELD_OPT_KEY, "id")  //当数据主键相同时,对比的字段,保存该字段大的数据  .option(DataSourceWriteOptions.PRECOMBINE_FIELD_OPT_KEY, "data_dt")  //指定分区列  .option(DataSourceWriteOptions.PARTITIONPATH_FIELD_OPT_KEY, "loc")  //并行度设置  .option("hoodie.insert.shuffle.parallelism", "2")  .option("hoodie.upsert.shuffle.parallelism", "2")  //表名设置  .option(HoodieWriteConfig.TABLE_NAME, "person_infos")  //关于Hive设置  //指定HiveServer2 连接url  .option(DataSourceWriteOptions.HIVE_URL_OPT_KEY,"jdbc:hive2://node1:10000")  //指定Hive 对应的库名  .option(DataSourceWriteOptions.HIVE_DATABASE_OPT_KEY,"default")  //指定Hive映射的表名称  .option(DataSourceWriteOptions.HIVE_TABLE_OPT_KEY,"infos1")  //Hive表映射对的分区字段  .option(DataSourceWriteOptions.HIVE_PARTITION_FIELDS_OPT_KEY,"loc")  //当设置为true时,注册/同步表到Apache Hive metastore,默认是false,这里就是自动创建表  .option(DataSourceWriteOptions.HIVE_SYNC_ENABLED_OPT_KEY,"true")  //如果分区格式不是yyyy/mm/dd ,需要指定解析类将分区列解析到Hive中  .option(DataSourceWriteOptions.HIVE_PARTITION_EXTRACTOR_CLASS_OPT_KEY,classOf[MultiPartKeysValueExtractor].getName)  .mode(SaveMode.Append)  .save("/hudi_data/person_infos")

复制代码

2)查询 Hive 中数据

hive> show tables;infos1

复制代码

hive> set hive.cli.print.header=true;
hive> select * from infos1;

复制代码

hive> select `_hoodie_commit_time`,id,name,age,loc,data_dt from infos1;

复制代码

3)更新表中数据,再次查询 Hive 中的数据

//4.更新数据,查询Hive数据//读取修改数据val updateDataDF: DataFrame = session.read.json("file:///D:\\2022IDEA_space\\SparkOperateHudi\\data\\updatedata.json")
//向Hudi 更新数据updateDataDF.write.format("org.apache.hudi")  //设置写出模式,默认就是COW  .option(DataSourceWriteOptions.TABLE_TYPE_OPT_KEY,DataSourceWriteOptions.COW_TABLE_TYPE_OPT_VAL)  .option(DataSourceWriteOptions.RECORDKEY_FIELD_OPT_KEY, "id")  .option(DataSourceWriteOptions.PRECOMBINE_FIELD_OPT_KEY, "data_dt")  .option(DataSourceWriteOptions.PARTITIONPATH_FIELD_OPT_KEY,"loc")  .option("hoodie.insert.shuffle.parallelism", "2")  .option("hoodie.upsert.shuffle.parallelism", "2")  .option(HoodieWriteConfig.TABLE_NAME, "person_infos")  //关于Hive设置  //指定HiveServer2 连接url  .option(DataSourceWriteOptions.HIVE_URL_OPT_KEY,"jdbc:hive2://node1:10000")  //指定Hive 对应的库名  .option(DataSourceWriteOptions.HIVE_DATABASE_OPT_KEY,"default")  //指定Hive映射的表名称  .option(DataSourceWriteOptions.HIVE_TABLE_OPT_KEY,"infos1")  //Hive表映射对的分区字段  .option(DataSourceWriteOptions.HIVE_PARTITION_FIELDS_OPT_KEY,"loc")  //当设置为true时,注册/同步表到Apache Hive metastore,默认是false,这里就是自动创建表  .option(DataSourceWriteOptions.HIVE_SYNC_ENABLED_OPT_KEY,"true")  //如果分区格式不是yyyy/mm/dd ,需要指定解析类将分区列解析到Hive中  .option(DataSourceWriteOptions.HIVE_PARTITION_EXTRACTOR_CLASS_OPT_KEY,classOf[MultiPartKeysValueExtractor].getName)  .mode(SaveMode.Append)  .save("/hudi_data/person_infos")

复制代码

每次查询都是查询最后一次数据结果

2、MOR 模式-SparkSQL 代码写入 Hudi 同时映射 Hive 表

1)MOR 代码如下

//1.创建对象val session: SparkSession = SparkSession.builder().master("local").appName("insertDataToHudi")  .config("spark.serializer", "org.apache.spark.serializer.KryoSerializer")  .getOrCreate()
//2.创建DataFrameval insertDF: DataFrame = session.read.json("file:///D:\\2022IDEA_space\\SparkOperateHudi\\data\\jsondata.json")
import org.apache.spark.sql.functions._//3.向Hudi中插入数据 - COW模式insertDF  .write.format("hudi")  //设置写出模式,默认就是COW  .option(DataSourceWriteOptions.TABLE_TYPE_OPT_KEY,DataSourceWriteOptions.MOR_TABLE_TYPE_OPT_VAL)  //设置主键列名称  .option(DataSourceWriteOptions.RECORDKEY_FIELD_OPT_KEY, "id")  //当数据主键相同时,对比的字段,保存该字段大的数据  .option(DataSourceWriteOptions.PRECOMBINE_FIELD_OPT_KEY, "data_dt")  //指定分区列  .option(DataSourceWriteOptions.PARTITIONPATH_FIELD_OPT_KEY, "loc")  //并行度设置  .option("hoodie.insert.shuffle.parallelism", "2")  .option("hoodie.upsert.shuffle.parallelism", "2")  //表名设置,不能重复,重复会报错  .option(HoodieWriteConfig.TABLE_NAME, "person_infos2")  //关于Hive设置  //指定HiveServer2 连接url  .option(DataSourceWriteOptions.HIVE_URL_OPT_KEY,"jdbc:hive2://node1:10000")  //指定Hive 对应的库名  .option(DataSourceWriteOptions.HIVE_DATABASE_OPT_KEY,"default")  //指定Hive映射的表名称  .option(DataSourceWriteOptions.HIVE_TABLE_OPT_KEY,"infos2")  //Hive表映射对的分区字段  .option(DataSourceWriteOptions.HIVE_PARTITION_FIELDS_OPT_KEY,"loc")  //当设置为true时,注册/同步表到Apache Hive metastore,默认是false,这里就是自动创建表  .option(DataSourceWriteOptions.HIVE_SYNC_ENABLED_OPT_KEY,"true")  //如果分区格式不是yyyy/mm/dd ,需要指定解析类将分区列解析到Hive中  .option(DataSourceWriteOptions.HIVE_PARTITION_EXTRACTOR_CLASS_OPT_KEY,classOf[MultiPartKeysValueExtractor].getName)  .mode(SaveMode.Append)  .save("/hudi_data/person_infos2")

复制代码

2)查询 Hive 表中的数据

hive> show tables;

复制代码

注意:infos2_ro 中存储的只是 Base 文件中数据(parquet 列式存储结果)

infos2_rt 中存储的是 Base 文件(Parquet 列式存储结果)+*log*(Avro 行式存储结果)

hive> select * from infos2_ro;

复制代码

目前只有 Base 文件数据,查询的就是全量数据

hive> select * from infos2_rt;

复制代码

目前只有 Base 文件数据,查询的就是全量数据

hive> select `_hoodie_commit_time`,id,name,age,loc,data_dt from infos2_ro;

复制代码

hive> select `_hoodie_commit_time`,id,name,age,loc,data_dt from infos2_rt;

复制代码

3)更新表中数据,再次查询 Hive 中的数据

//4.更新数据,查询Hive数据//读取修改数据val updateDataDF: DataFrame = session.read.json("file:///D:\\2022IDEA_space\\SparkOperateHudi\\data\\updatedata.json")
//向Hudi 更新数据,注意,必须指定Hive对应配置updateDataDF.write.format("org.apache.hudi")  //设置写出模式,默认就是COW  .option(DataSourceWriteOptions.TABLE_TYPE_OPT_KEY,DataSourceWriteOptions.MOR_TABLE_TYPE_OPT_VAL)  .option(DataSourceWriteOptions.RECORDKEY_FIELD_OPT_KEY, "id")  .option(DataSourceWriteOptions.PRECOMBINE_FIELD_OPT_KEY, "data_dt")  .option(DataSourceWriteOptions.PARTITIONPATH_FIELD_OPT_KEY,"loc")  .option("hoodie.insert.shuffle.parallelism", "2")  .option("hoodie.upsert.shuffle.parallelism", "2")  .option(HoodieWriteConfig.TABLE_NAME, "person_infos2")  //关于Hive设置  //指定HiveServer2 连接url  .option(DataSourceWriteOptions.HIVE_URL_OPT_KEY,"jdbc:hive2://node1:10000")  //指定Hive 对应的库名  .option(DataSourceWriteOptions.HIVE_DATABASE_OPT_KEY,"default")  //指定Hive映射的表名称  .option(DataSourceWriteOptions.HIVE_TABLE_OPT_KEY,"infos2")  //Hive表映射对的分区字段  .option(DataSourceWriteOptions.HIVE_PARTITION_FIELDS_OPT_KEY,"loc")  //当设置为true时,注册/同步表到Apache Hive metastore,默认是false,这里就是自动创建表  .option(DataSourceWriteOptions.HIVE_SYNC_ENABLED_OPT_KEY,"true")  //如果分区格式不是yyyy/mm/dd ,需要指定解析类将分区列解析到Hive中  .option(DataSourceWriteOptions.HIVE_PARTITION_EXTRACTOR_CLASS_OPT_KEY,classOf[MultiPartKeysValueExtractor].getName)  .mode(SaveMode.Append)  .save("/hudi_data/person_infos2")

复制代码

查询 Hive 中对应两张表的数据结果

查询 Base 文件中的数据

hive> select `_hoodie_commit_time`,id,name,age,loc,data_dt from infos2_ro;

复制代码

查询 Base 文件+log 文件中数据,可以看到查询到的是修改后的结果数据

hive> select `_hoodie_commit_time`,id,name,age,loc,data_dt from infos2_rt;

复制代码

三、手动层面集成 Hudi 与 Hive

如果已经存在 Hudi 数据,我们也可以手动创建对应的 Hive 表来映射对应的 Hudi 数据,使用 Hive SQL 来操作 Hudi。例如使用如下代码在 HDFS 中存储 Hudi 数据,这里采用 MOR 模式写入数据,方便后期测试:

1)向 Hudi 表中写入数据

//1.创建对象val session: SparkSession = SparkSession.builder().master("local").appName("insertDataToHudi")  .config("spark.serializer", "org.apache.spark.serializer.KryoSerializer")  .getOrCreate()
//2.创建DataFrameval insertDF: DataFrame = session.read.json("file:///D:\\2022IDEA_space\\SparkOperateHudi\\data\\jsondata.json")
import org.apache.spark.sql.functions._//3.向Hudi中插入数据 - COW模式insertDF  .write.format("hudi")  //设置写出模式,默认就是COW  .option(DataSourceWriteOptions.TABLE_TYPE_OPT_KEY,DataSourceWriteOptions.MOR_TABLE_TYPE_OPT_VAL)  //设置主键列名称  .option(DataSourceWriteOptions.RECORDKEY_FIELD_OPT_KEY, "id")  //当数据主键相同时,对比的字段,保存该字段大的数据  .option(DataSourceWriteOptions.PRECOMBINE_FIELD_OPT_KEY, "data_dt")  //指定分区列  .option(DataSourceWriteOptions.PARTITIONPATH_FIELD_OPT_KEY, "loc")  //并行度设置  .option("hoodie.insert.shuffle.parallelism", "2")  .option("hoodie.upsert.shuffle.parallelism", "2")  //表名设置  .option(HoodieWriteConfig.TABLE_NAME, "person_infos3")  .mode(SaveMode.Append)  .save("/hudi_data/person_infos3")

复制代码

2)在 Hive 中创建对应的表数据

在 Hive 中创建表 person3_ro,映射 Base 数据,相当于前面的 ro 表:

// 创建外部表,这种方式只会查询出来parquet数据文件中的内容,但是刚刚更新或者删除的数据不能查出来CREATE EXTERNAL TABLE `person3_ro`(`_hoodie_commit_time` string,`_hoodie_commit_seqno` string,`_hoodie_record_key` string,`_hoodie_partition_path` string,`_hoodie_file_name` string,`id` bigint,`name` string,`age` bigint,`data_dt` string)PARTITIONED BY (`loc` string) ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' STORED AS INPUTFORMAT 'org.apache.hudi.hadoop.HoodieParquetInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat' LOCATION 'hdfs://mycluster/hudi_data/person_infos3';

复制代码

建好以上对应的表之后,由于有分区,还看不到数据,所以这里需要我们手动映射分区数据:

alter table person3_ro add if not exists partition(loc="beijing") location 'hdfs://mycluster/hudi_data/person_infos3/beijing';alter table person3_ro add if not exists partition(loc='chongqing') location 'hdfs://mycluster/hudi_data/person_infos3/chongqing';alter table person3_ro add if not exists partition(loc='hainai') location 'hdfs://mycluster/hudi_data/person_infos3/hainai';alter table person3_ro add if not exists partition(loc='hunan') location 'hdfs://mycluster/hudi_data/person_infos3/hunan';alter table person3_ro add if not exists partition(loc='shandong') location 'hdfs://mycluster/hudi_data/person_infos3/shandong';alter table person3_ro add if not exists partition(loc='shanghai') location 'hdfs://mycluster/hudi_data/person_infos3/shanghai';alter table person3_ro add if not exists partition(loc='shenzhen') location 'hdfs://mycluster/hudi_data/person_infos3/shenzhen';alter table person3_ro add if not exists partition(loc='tianjin') location 'hdfs://mycluster/hudi_data/person_infos3/tianjin';

复制代码

查看表数据

在 Hive 中创建表 person3_rt,映射 Base+log 数据,相当于 rt 表,并映射分区:

// 这种方式会将基于Parquet的基础列式文件、和基于行的Avro日志文件合并在一起呈现给用户。CREATE EXTERNAL TABLE `person3_rt`(`_hoodie_commit_time` string,`_hoodie_commit_seqno` string,`_hoodie_record_key` string,`_hoodie_partition_path` string,`_hoodie_file_name` string,`id` bigint,`name` string,`age` bigint,`data_dt` string)PARTITIONED BY (`loc` string) ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' STORED AS INPUTFORMAT 'org.apache.hudi.hadoop.realtime.HoodieParquetRealtimeInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat' LOCATION 'hdfs://mycluster/hudi_data/person_infos3'; 

复制代码

加载对应分区数据数据

alter table person3_rt add if not exists partition(loc="beijing") location 'hdfs://mycluster/hudi_data/person_infos3/beijing';alter table person3_rt add if not exists partition(loc='chongqing') location 'hdfs://mycluster/hudi_data/person_infos3/chongqing';alter table person3_rt add if not exists partition(loc='hainai') location 'hdfs://mycluster/hudi_data/person_infos3/hainai';alter table person3_rt add if not exists partition(loc='hunan') location 'hdfs://mycluster/hudi_data/person_infos3/hunan';alter table person3_rt add if not exists partition(loc='shandong') location 'hdfs://mycluster/hudi_data/person_infos3/shandong';alter table person3_rt add if not exists partition(loc='shanghai') location 'hdfs://mycluster/hudi_data/person_infos3/shanghai';alter table person3_rt add if not exists partition(loc='shenzhen') location 'hdfs://mycluster/hudi_data/person_infos3/shenzhen';alter table person3_rt add if not exists partition(loc='tianjin') location 'hdfs://mycluster/hudi_data/person_infos3/tianjin';

复制代码

查看结果数据

3)使用代码修改 Hudi 表中的数据:

修改数据如下:

{"id":1,"name":"ls1","age":40,"loc":"beijing","data_dt":"20210709"}{"id":2,"name":"ls2","age":50,"loc":"shanghai","data_dt":"20210710"}{"id":3,"name":"ls3","age":60,"loc":"ttt","data_dt":"20210711"}

复制代码

//4.更新数据,查询Hive数据//读取修改数据val updateDataDF: DataFrame = session.read.json("file:///D:\\2018IDEA_space\\SparkOperateHudi\\data\\updatedata.json")
//向Hudi 更新数据updateDataDF.write.format("org.apache.hudi")  //设置写出模式,默认就是COW  .option(DataSourceWriteOptions.TABLE_TYPE_OPT_KEY,DataSourceWriteOptions.MOR_TABLE_TYPE_OPT_VAL)  .option(DataSourceWriteOptions.RECORDKEY_FIELD_OPT_KEY, "id")  .option(DataSourceWriteOptions.PRECOMBINE_FIELD_OPT_KEY, "data_dt")  .option(DataSourceWriteOptions.PARTITIONPATH_FIELD_OPT_KEY,"loc")  .option("hoodie.insert.shuffle.parallelism", "2")  .option("hoodie.upsert.shuffle.parallelism", "2")  .option(HoodieWriteConfig.TABLE_NAME, "person_infos3")  .mode(SaveMode.Append)  .save("/hudi_data/person_infos3")

复制代码

4)继续查询对应的两张 Hive 表数据

由于分区 “ttt”是新加入的分区,需要手动添加下分区才能在对应的 Hive 表中正常查询

alter table person3_ro add if not exists partition(loc="ttt") location 'hdfs://mycluster/hudi_data/person_infos3/ttt';alter table person3_rt add if not exists partition(loc="ttt") location 'hdfs://mycluster/hudi_data/person_infos3/ttt';

查询表 person3_ro

hive> select * from person3_ro;

查询表 person3_rt

hive> select * from person3_rt;

此外,我们也可以不需要每次都自己手动添加分区,而是创建好对应的 Hive 表后,在代码中向 Hudi 中写数据时,指定对应的 Hive 参数即可,这样写入的数据自动会映射到 Hive 中。

我们可以删除 Hive 对应的表数据重新创建以及第一次加载分区,再后续写入 Hudi 表数据时,代码如下,就不需要每次都手动加载 Hive 分区数据。

//5.更新数据,指定Hive配置项//读取修改数据val updateDataDF: DataFrame = session.read.json("file:///D:\\2022IDEA_space\\SparkOperateHudi\\data\\updatedata.json")//向Hudi 更新数据updateDataDF.write.format("org.apache.hudi")  //设置写出模式,默认就是COW  .option(DataSourceWriteOptions.TABLE_TYPE_OPT_KEY,DataSourceWriteOptions.MOR_TABLE_TYPE_OPT_VAL)  .option(DataSourceWriteOptions.RECORDKEY_FIELD_OPT_KEY, "id")  .option(DataSourceWriteOptions.PRECOMBINE_FIELD_OPT_KEY, "data_dt")  .option(DataSourceWriteOptions.PARTITIONPATH_FIELD_OPT_KEY,"loc")  .option("hoodie.insert.shuffle.parallelism", "2")  .option("hoodie.upsert.shuffle.parallelism", "2")  .option(HoodieWriteConfig.TABLE_NAME, "person_infos3")  //关于Hive设置  //指定HiveServer2 连接url  .option(DataSourceWriteOptions.HIVE_URL_OPT_KEY,"jdbc:hive2://node1:10000")  //指定Hive 对应的库名  .option(DataSourceWriteOptions.HIVE_DATABASE_OPT_KEY,"default")  //指定Hive映射的表名称  .option(DataSourceWriteOptions.HIVE_TABLE_OPT_KEY,"person3")  //Hive表映射对的分区字段  .option(DataSourceWriteOptions.HIVE_PARTITION_FIELDS_OPT_KEY,"loc")  //当设置为true时,注册/同步表到Apache Hive metastore,默认是false,这里就是自动创建表  .option(DataSourceWriteOptions.HIVE_SYNC_ENABLED_OPT_KEY,"true")  //如果分区格式不是yyyy/mm/dd ,需要指定解析类将分区列解析到Hive中  .option(DataSourceWriteOptions.HIVE_PARTITION_EXTRACTOR_CLASS_OPT_KEY,classOf[MultiPartKeysValueExtractor].getName)  .mode(SaveMode.Append)  .save("/hudi_data/person_infos3")

查询 Hive 表 peson3_ro 数据

查询 Hive 表 person3_rt 数据

四、SparkSQL 操作映射的 Hive 表

将 Hudi 数据映射到 Hive 后,我们可以使用 SparkSQL 来进行操作 Hive 表进行处理。操作代码如下:

val session: SparkSession = SparkSession.builder().master("local").appName("test")  .config("hive.metastore.uris", "thrift://node1:9083")  .enableHiveSupport()  .getOrCreate()
session.sql("use default")session.sql(  """    | select id,name,age,loc,data_dt from person3_rt  """.stripMargin).show()session.sql(  """    | select sum(age) as totalage from person3_rt  """.stripMargin).show()

复制代码

我们可以看到如果针对 Hudi 表中的数据进行修改,那么 SpakSQL 读取到的就是最新修改后的结果数据。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值