本文介绍云数据库 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的时间。