
# 读取Hudi mor表视图
#### 操作场景
读时合并表（Merge On Read）也简称mor表，使用列格式parquet和行格式Avro两种方式混合存储数据。其中parquet格式文件用于存储基础数据，Avro格式文件（也可叫做log文件）用于存储增量数据。
- 优点：由于写入数据先写delta log，且delta log较小，所以写入成本较低。
- 缺点：需要定期合并整理compact，否则碎片文件较多。读取性能较差，因为需要将delta log和老数据文件合并。
 
#### 读取Hudi mor表示例
mor表同步给Hive后，会在Hive表中同步出："表名+后缀_rt"和"表名+后缀_ro"两张表。其中后缀为rt表代表实时视图，后缀为ro的表代表读优化视图。例如：同步给Hive的Hudi表名为**${table_name}** ， 同步Hive后hive表中多出两张表分别为**${table_name}_rt** 和**${table_name}_ro**。
- 实时视图读取（Hive，SparkSQL为例）：直接读取Hive里面存储的后缀为_rt的Hudi表即可。
  ```
  select count(*) from ${table_name}_rt;
  ```
  
- 实时视图读取（Spark dataSource API为例）：和cow表一样，请参考cow表相关操作。
- 增量视图读取（Hive为例）：
  ```
  set hive.input.format=org.apache.hudi.hadoop.hive.HoodieCombineHiveInputFormat; // sparksql 不需要指定
  set hoodie.${table_name}.consume.mode=INCREMENTAL;
  set hoodie.${table_name}.consume.max.commits=3;
  set hoodie.${table_name}.consume.start.timestamp=20201227153030;
  select count(*) from default.${table_name}_rt where `_hoodie_commit_time`>'20201227153030';
  ```
  
- 增量视图读取（SparkSQL为例）：
  ```
  set hoodie.${table_name}.consume.mode=INCREMENTAL;
  set hoodie.${table_name}.consume.start.timestamp=20201227153030;  // 指定初始增量拉取commit
  set hoodie.${table_name}.consume.end.timestamp=20210308212318;  // 指定增量拉取结束commit，如果不指定的话采用最新的commit
  select count(*) from default.${table_name}_rt where `_hoodie_commit_time`>'20201227153030';
  ```
  
- 增量视图（Spark dataSource API为例）：和cow表一样，请参考cow表相关操作。
- 读优化视图读取（Hive，SparkSQL为例）：直接读取Hive里面存储的后缀为_ro的Hudi表即可。
  ```
  select count(*) from ${table_name}_ro;
  ```
  
- 读优化视图读取（Spark dataSource API为例）：和读普通的dataSource表类似。 必须指定查询类型QUERY_TYPE_OPT_KEY为QUERY_TYPE_READ_OPTIMIZED_OPT_VAL。
  ```
  spark.read.format("hudi")
  .option(QUERY_TYPE_OPT_KEY, QUERY_TYPE_READ_OPTIMIZED_OPT_VAL) // 指定查询类型为读优化视图
  .load("/tmp/default/mor_bugx/") // 指定读取的Hudi表路径
  .createTempView("mycall")
  spark.sql("select * from mycall").show(100)
  ```
  
 
