Hudi数据源

本文介绍云数据库 SelectDB 版与Hudi数据源进行对接使用的流程,帮助您对Hudi数据源进行联邦分析。

注意事项

Hudi表支持的查询类型如下。

表类型

支持的查询类型

Copy On Write

Snapshot Query + Time Travel

Merge On Read

Snapshot Queries + Read Optimized Queries + Time Travel

目前支持Hive Metastore和兼容Hive Metastore类型(例如Alibaba DLF)的Catalog。

创建Catalog

和Hive Catalog基本一致,此处仅提供简单示例。其他示例请参见Hive数据源

CREATE CATALOG hudi PROPERTIES (
    'type'='hms',
    'hive.metastore.uris' = 'thrift://172.21.0.1:7004',
    'hadoop.username' = 'hive',
    'dfs.nameservices'='your- nameservice',
    'dfs.ha.namenodes.your-nameservice'='nn1,nn2',
    'dfs.namenode.rpc-address.your-nameservice.nn1'='172.21.0.2:4007',
    'dfs.namenode.rpc-address.your-nameservice.nn2'='172.21.0.3:4007',
    'dfs.client.failover.proxy.provider.your-nameservice'='org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider'
);

列类型映射

和Hive Catalog一致,请参见Hive数据源的列类型映射

Skip Merge

Spark在创建Hudi MOR表时,会创建_ro后缀的Read Optimize表。SelectDB读取Read Optimize表时会跳过log文件的合并。SelectDB判定一个表是否为Read Optimize表并不是通过_ro后缀,而是通过Hive InputFormat信息。您可以通过SHOW CREATE TABLE命令观察COW/MOR/Read Optimize表的InputFormat是否相同。

此外,SelectDB支持在Catalog Properties添加hoodie相关的配置,配置项兼容Spark Datasource Configs。所以您可以在Catalog Properties中添加hoodie.datasource.merge.type=skip_merge以跳过合并log文件。

Time Travel

在Hudi中,每次对表的写操作都会产生一个新的快照(Snapshot)。

默认情况下,SelectDB的读请求只会读取Hudi最新版本的快照,您可以使用FOR TIME AS OF语句,根据快照的时间(时间格式和Hudi官网保持一致)读取历史版本的数据。示例如下:

SELECT * FROM hudi_tbl FOR TIME AS OF "2022-10-07 17:20:37";
SELECT * FROM hudi_tbl FOR TIME AS OF "20221007172037";

Hudi表不支持FOR VERSION AS OF语句,使用该语法查询Hudi表将报错。

查询性能分析

SelectDB使用Parquet Native Reader读取COW表的数据文件,使用Java SDK(通过JNI调用hudi-bundle)读取MOR表的数据文件。在Upsert场景下,MOR表中依然会有数据文件没有被更新,这部分文件可以通过Parquet Native Reader读取。

您可以通过EXPLAIN命令查看Hudi Scan的执行计划,hudiNativeReadSplits表示有多少split文件通过Parquet Native Reader读取。

|0:VHUDI_SCAN_NODE                                                             |
|      table: minbatch_mor_rt                                                  |
|      predicates: `o_orderkey` = 100030752                                    |
|      inputSplitNum=810, totalFileSize=5645053056, scanRanges=810             |
|      partition=80/80                                                         |
|      numNodes=6                                                              |
|      hudiNativeReadSplits=717/810                                            |

您可以通过profile查看Java SDK的性能,例如:

  -  HudiJniScanner:  0ns
  -  FillBlockTime:  31.29ms
  -  GetRecordReaderTime:  1m5s
  -  JavaScanTime:  35s991ms
  -  OpenScannerTime:  1m6s

其中:

  • OpenScannerTime:创建并初始化JNI Reader的时间。

  • JavaScanTime:Java SDK读取数据的时间。

  • FillBlockTime:Java数据拷贝为C++数据的时间。

  • GetRecordReaderTime:调用Java SDK并创建Hudi Record Reader的时间。