
# 配置Hive读取Hudi表
在数据湖场景中，Hudi（Hadoop Upserts Deletes and Incrementals）作为流式数据湖存储格式，支持高效的数据更新和增量查询。业务系统通过Spark或Flink将数据写入Hudi表后，可能需要使用Hive进行复杂的数据分析查询。然而，Hudi表的数据格式与Hive原生表格式不同，直接在Hive中查询Hudi表会遇到兼容性问题。如何将Hudi表的数据映射为Hive可查询的外部表，并支持实时视图、读优化视图和增量视图等多种查询模式？MRS Hive提供Hudi表映射功能，可以将Hudi源表映射为Hive外部表，支持多种视图查询模式，满足不同的数据分析需求。
本文介绍如何配置Hive读取Hudi表。
#### Hudi表对应的Hive外部表介绍
Hudi源表对应一份HDFS的数据，通过Spark组件、Flink组件或者Hudi客户端，可以将Hudi表的数据映射为Hive外部表，基于该外部表，Hive可以进行实时视图查询、读优化视图查询以及增量视图查询。
根据Hudi源表的类型的不同，提供不同的视图查询：
- Hudi源表类型为Copy On Write时，可以映射为Hive的一张外部表，该表可以提供实时视图查询以及增量视图查询。
- Hudi源表类型为Merge On Read时，可以映射为Hive的两张外部表（ro表和rt表），ro表提供读优化视图查询，rt表提供实时视图查询以及增量视图查询。
 
#### 约束与限制
- 不能对Hudi表映射的Hive外部表做增删改操作（即insert、update、delete、load、merge、alter、msck），只支持查询操作（select）。
- 表授权 不支持修改类权限操作（即update、Alter、write、All）。
  
- 备份与恢复 由于ro表和rt表均由同一个Hudi源表映射的，备份其中一张表，另一张也会跟着备份，恢复也是同时恢复的，因此只需备份其中一张表即可。
  
- 组件版本
  - Hive：FusionInsight_HD_xxx，Hive内核版本3.1.0。
  
  - Spark2x：FusionInsight_Spark2x_xxx，Hudi内核版本：0.11.0。
   
 
#### 创建Hudi表对应的Hive外部表
可在spark-shell或spark-sql中创建Hudi表并插入数据，具体操作请参见[使用Spark Shell创建Hudi表](https://support.huaweicloud.com/cmpntguide-lts-mrs/mrs_01_24033.html)或[使用Spark SQL操作Hudi表](https://support.huaweicloud.com/cmpntguide-lts-mrs/mrs_01_300441.html)。
Hudi表数据在入湖的时候一般会同步到Hive外部表，此时在Beeline中可以直接查询到对应的Hive外部表，如果没有同步到Hive外部表，则可以通过Hudi客户端工具手动同步，具体步骤可参考[将Hudi表数据同步到Hive](https://support.huaweicloud.com/cmpntguide-lts-mrs/mrs_01_24064.html)。
#### 查询Hudi表对应的Hive外部表
使用Hive对Hudi表进行增量查询前，需要设置[表1]的3个参数，这3个参数是表级别的参数，每个Hudi源表都对应3个参数，其中*hudisourcetablename*表示Hudi源表的表名（需注意不是Hive外部表的表名），需根据实际情况进行修改。
MRS 3.6.0-LTS及之后版本，使用Tez引擎执行Hive查询Hudi表任务时，如果报错"java.lang.UnsupportedOperationException: Not expecting to handle any events"，则可以在Hive客户端执行以下命令关闭动态分区裁剪功能后，再重新执行查询命令。
```
set hive.tez.dynamic.partition.pruning=false;
```
 表1参数说明 
| 参数                                                   | 参数说明                                                                                                                                                                                                                                                                                                                                                                 | 默认值 |
|:---|:---|:---|
| hoodie.*hudisourcetablename*.consume.mode            | Hudi表的查询模式。 - 增量查询：INCREMENTAL。  - 非增量查询：不设置或者设为"SNAPSHOT"。                                                                                                                  | 无   |
| hoodie.*hudisourcetablename*.consume.start.timestamp | Hudi表增量查询的起始时间。 - 增量查询：增量查询的起始时间。  - 非增量查询：不设置。                                                                                                                           | 无   |
| hoodie.*hudisourcetablename*.consume.max.commits     | Hudi表增量查询基于"hoodie.hudisourcetablename.consume.start.timestamp"之后commit的次数。 - 增量查询：提交次数，例如设置为3，表示增量查询从指定的起始时间之后commit 3次的数据，设为-1时，表示增量查询从指定的起始时间之后提交的所有数据。  - 非增量查询：不设置。   | 无   |
   
Hudi表查询操作如下：
1. 以Hive客户端安装用户登录安装客户端的节点。
2. 执行以下命令，切换到客户端安装目录，配置环境变量并认证用户。 
   切换到客户端安装目录：
   ```
   cd 客户端安装目录
   ```
   加载环境变量
   ```
   source bigdata_env
   ```
   认证用户，如果集群未启用Kerberos认证（普通模式），请跳过该操作：
   ```
   kinit Hive业务用户
   ```
   
   
3. 执行以下命令登录Hive客户端。 
   ```
   beeline
   ```
   
   
4. Hudi表查询。 
   - **Copy On Write类型Hudi表查询**
     例如cow类型的Hudi源表的表名为**hudicow** ，映射为Hive外部表的表名为**hudicow**。
     - cow表实时视图查询：
       ```
       select * from hudicow;
       ```
       
     
     - cow表增量查询，需要根据Hudi源表的表名设置3个增量查询参数，且增量查询语句的where子句必须包含"\`_hoodie_commit_time\`\>'*xxx* '"，其中的*xxx* 为"hoodie.hudisourcetablename.consume.start.timestamp"增量参数的值。
       设置Hudi表的查询模式为"INCREMENTAL"：
       ```
       set hoodie.hudicow.consume.mode= INCREMENTAL;
       ```
       设置Hudi表增量查询的提交次数：
       ```
       set hoodie.hudicow.consume.max.commits=3;
       ```
       设置Hudi表增量查询的起始时间：
       ```
       set hoodie.hudicow.consume.start.timestamp= 20200427114546;
       ```
       执行cow表增量查询：
       ```
       select count(*) from hudicow where `_hoodie_commit_time`>'20200427114546';
       ```
       
      
   
   - **Merge On Read类型Hudi表的查询**
     例如mor类型的Hudi源表的表名为**hudimor** ，映射为两张Hive外部表**hudimor_ro** （ro表）和**hudimor_rt**（rt表）。
     - ro表提供读优化视图查询：
       ```
       select * from hudicow_ro;
       ```
       
     
     - rt的实时视图查询：
       ```
       select * from hudicow_rt;
       ```
       
     
     - rt表的增量查询，需要根据Hudi源表的表名设置3个增量查询参数，且增量查询语句的where子句必须包含"\`_hoodie_commit_time\`\>'*xxx* '"，其中的*xxx* 为"hoodie.hudisourcetablename.consume.start.timestamp"增量参数的值。
       设置Hudi表的查询模式：
       - 设置Hudi表为增量查询：
         ```
         set hoodie.hudimor.consume.mode=INCREMENTAL;
         ```
         
       
       - 设置Hudi表为其他查询模式：
         ```
         set hoodie.hudisourcetablename.consume.mode=SNAPSHOT;
         ```
         
       
       
       设置Hudi表增量查询的提交次数：
       ```
       set hoodie.hudimor.consume.max.commits=-1;
       ```
       设置Hudi表增量查询的起始时间：
       ```
       set hoodie.hudimor.consume.start.timestamp=20210207144611;
       ```
       执行rt表查询操作：
       ```
       select * from hudimor_rt where `_hoodie_commit_time`>'20210207144611';
       ```
       
      
   
   
   
   
**验证操作：**
执行查询后，检查返回结果：
- 实时视图查询应返回最新的数据状态。
- 读优化视图查询应返回已合并的基础数据。
- 增量查询应返回指定时间范围内的变更数据。
 
#### 查询Hudi的Schema演进表对应的Hive外部表
如果该Hudi表为Schema演进表（表的字段执行过修改），则在Hive客户端查询该表时还需额外设置一个参数：
```
set hive.exec.schema.evolution=true;
```
该参数设置为"true"后，Hive会自动适应Hudi表的Schema变化，确保查询结果基于最新的表结构，以提供准确和一致的查询结果。
例如以cow表实时视图的查询举例，其他各个视图的查询都要额外添加该参数：
设置"hive.exec.schema.evolution"为"true"：
```
set hive.exec.schema.evolution=true;
```
查询Hive外部表：
```
select * from hudicow;
```
#### 常见问题
- **查询Hudi表报错"Table not found"**
  Hudi表数据未同步到Hive外部表，或Hive外部表名称不正确。
  请确认Hudi表数据已同步到Hive外部表。如果未同步，请参考将Hudi表数据同步到Hive手动同步。检查Hive外部表名称是否正确。
  
- **增量查询返回空结果**
  增量查询参数设置不正确，或指定的起始时间范围内没有数据变更。
  请检查consume.mode、consume.start.timestamp、consume.max.commits三个参数是否正确设置。确认起始时间在Hudi表的数据变更时间范围内。where子句中的_hoodie_commit_time值必须与consume.start.timestamp参数值一致。
  
- **MOR表查询性能较差**
  MOR表的rt表在查询时需要合并基础文件和日志文件，查询开销较大。
  如果对数据实时性要求不高，建议使用ro表进行读优化视图查询，性能更好。或者定期触发compaction操作，将日志文件合并到基础文件中。
  
 
#### 相关文档
- 了解Hive数据操作，请参考[Hive客户端使用实践](https://support.huaweicloud.com/cmpntguide-lts-mrs/mrs_01_0952.html)。
- 了解如何创建Hive用户并绑定角色，请参考[创建Hive用户并绑定角色](https://support.huaweicloud.com/cmpntguide-lts-mrs/mrs_01_0949.html)。
- 了解Hive常见问题，请参考[Hive常见问题](https://support.huaweicloud.com/cmpntguide-lts-mrs/mrs_01_1752.html)。
 
