
# 读取Hudi cow表视图
#### 操作场景
写时复制表（Copy On Write）也简称cow表，使用parquet文件存储数据，内部的更新操作需要通过重写原始parquet文件完成。
- 优点：读取时，只读取对应分区的一个数据文件即可，较为高效。
- 缺点：数据写入的时候，需要复制一个先前的副本再在其基础上生成新的数据文件，这个过程比较耗时。且由于耗时，读请求读取到的数据相对就会滞后。
Hudi cow表支持以下三种视图类型，用户可根据业务需求选择合适的读取方式：
- **实时视图（Snapshot/Real-time View）**：读取cow表最新已提交的parquet文件数据，反映表中最新的一致性状态。适用于需要获取全量最新数据的场景，如全表统计、实时报表查询等。
- **增量视图（Incremental View）**：读取指定commit时间范围内的增量数据，仅返回该时间段内发生变化的数据记录。适用于增量数据同步、变更数据捕获（CDC）等场景。
- **读优化视图（Read Optimized View）**：仅读取parquet文件（已压缩和合并的列式存储文件），不读取日志文件。对于cow表而言，由于cow表本身仅使用parquet文件存储数据，因此读优化视图等同于实时视图。
 
#### 读取Hudi cow表示例
- 实时视图读取（Hive，SparkSQL为例）：直接读取Hive里面存储的Hudi表即可，**${table_name}** 表示表名称。
  ```
  select count(*) from ${table_name};
  ```
  
- 实时视图读取（Spark dataSource API为例）：和读普通的dataSource表类似。 必须指定查询类型QUERY_TYPE_OPT_KEY为QUERY_TYPE_SNAPSHOT_OPT_VAL，**${table_name}**表示表名称。
  ```
  spark.read.format("hudi")
  .option(QUERY_TYPE_OPT_KEY, QUERY_TYPE_SNAPSHOT_OPT_VAL) // 指定查询类型为实时视图模式
  .load("/tmp/default/cow_bugx/") // 指定读取的Hudi表路径
  .createTempView("mycall")
  spark.sql("select * from mycall").show(100)
  ```
  
- 增量视图读取（Hive为例，**${table_name}** 表示表名称）：
  ```
  set hoodie.${table_name}.consume.mode=INCREMENTAL;  //设置增量读取模式
  set hoodie.${table_name}.consume.max.commits=3;  // 指定最大消费的commits数量
  set hoodie.${table_name}.consume.start.timestamp=20201227153030;  // 指定初始增量拉取commit
  select count(*) from default.${table_name} where `_hoodie_commit_time`>'20201227153030'; // 这个过滤条件必须加且值为初始增量拉取的commit。
  ```
  
- 增量视图读取（SparkSQL为例，**${table_name}** 表示表名称）：
  ```
  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} where `_hoodie_commit_time`>'20201227153030'; // 这个过滤条件必须加且值为初始增量拉取的commit。
  ```
  
- 增量视图读取（Spark dataSource API为例）： 必须指定查询类型QUERY_TYPE_OPT_KEY为增量模式QUERY_TYPE_INCREMENTAL_OPT_VAL
  ```
  spark.read.format("hudi")  
  .option(QUERY_TYPE_OPT_KEY, QUERY_TYPE_INCREMENTAL_OPT_VAL) // 指定查询类型为增量模式
  .option(BEGIN_INSTANTTIME_OPT_KEY, "20210308212004")  // 指定初始增量拉取commit
  .option(END_INSTANTTIME_OPT_KEY, "20210308212318")  // 指定增量拉取结束commit
  .load("/tmp/default/cow_bugx/")  // 指定读取的Hudi表路径
  .createTempView("mycall")  // 注册为spark临时表
  spark.sql("select * from mycall where `_hoodie_commit_time`>'20210308211131'") // 开始查询，和hive增量查询语句一样
  .show(100, false)
  ```
  
- 读优化视图：cow表读优化视图等同于实时视图。
 
#### 常见问题
**Q：增量视图读取时，时间戳的格式是什么？**
A：时间戳格式为yyyyMMddHHmmss，例如20201227153030表示2020年12月27日15时30分30秒。请确保start.timestamp和end.timestamp使用正确的格式，否则可能导致查询结果为空或报错。
**Q：如何获取Hudi表的commit时间戳？**
A：可以通过Hudi CLI或Hive查询_hoodie_commit_time字段获取commit时间戳。commit时间戳的格式为yyyyMMddHHmmss，表示数据提交的时间。
**Q：增量视图读取时，过滤条件_hoodie_commit_time为什么必须加？**
A：Hudi增量视图通过_hoodie_commit_time字段过滤增量数据，该条件用于限定返回数据的commit时间范围。如果不加此过滤条件，Hudi将无法识别增量读取的起始时间，可能导致返回全量数据或查询失败。
**Q：实时视图和增量视图应该如何选择？**
A：如果您需要获取表的最新全量数据，请使用实时视图；如果您只需要获取指定时间范围内的变更数据（如增量同步场景），请使用增量视图。
#### 相关文档
- 创建Hudi表，具体请参考[CREATE TABLE](https://support.huaweicloud.com/cmpntguide-lts-mrs/mrs_01_24264.html)。
- 读取Hudi mor表视图，具体请参考[读取Hudi cow表视图](https://support.huaweicloud.com/cmpntguide-lts-mrs/mrs_01_24098.html)。
 
