背景
Hudi 源表对应一份 HDFS 数据,通过 Spark,Flink 组件或者 Hudi CLI,可以将 Hudi 表的数据映射为 Hive 外部表,基于该外部表, Hive可以方便的进行实时视图,读优化视图以及增量视图的查询。
Hive On Hudi 集成
这里以 hive3.1.1、hudi 0.9.0为例, 其他版本类似
1)将 hudi-hadoop-mr-bundle-0.9.0xxx.jar , hudi-hive-sync-bundle-0.9.0xx.jar 放到 hiveserver 节点的lib目录下;
2)修改 hive-site.xml 找到 hive.default.aux.jars.path
以及 hive.aux.jars.path
这两个配置项,将第一步中的jar包全路径给配置上去;
配置后大概长这个样子:
<name>hive.default.aux.jars.path</name>
<value>xxxx,jar,xxxx,jar,file:///mypath/hudi-hadoop-mr-bundle-0.9.0xxx.jar,file:///mypath/hudi-hive-sync-bundle-0.9.0xx.jar</value>
3) 配置完后请重启 hive-server;
4) 对于 Hudi 的 bootstrap 表(tez查询),除了要添加 hudi-hadoop-mr-bundle-0.9.0xxx.jar、hudi-hive-sync-bundle-0.9.0xx.jar 这两个jar包, 还需把 hbase-shaded-miscellaneous-xxx.jar、hbase-metric-api-xxx.jar、hbase-metrics-xxx.jar、hbase-protocol-shaded-xx.jar、hbase-shaded-protobuf-xxx.jar、htrce-core4-4.2.0xxxx.jar 按上述步骤添加进去。
创建 Hive 外表
一般来说 Hudi 表在用 Spark 或者 Flink 写入数据时会自动同步到 Hive 外部表, 此时可以直接通过 beeline 查询同步的外部表, 若写入引擎没有开启自动同步,则需要手动利用 hudi 客户端工具 run_hive_sync_tool.sh 进行同步具体可以参考官网查看相关参数。
查询 Hive 外表
操作前提
使用 Hive 查询 Hudi 表前,需要通过set命令设置 hive.input.format
,否则会出现数据重复,查询异常等错误,如下面这个报错就是典型的没有设置 hive.input.format
导致的:
java.lang.IllegalArgumentException: HoodieRealtimeReader can oly work on RealTimeSplit and not with xxxxxxxxxx
除此之外对于增量查询,还需要 set 命令额外设置3个参数,
set hoodie.mytableName.consume.mode=INCREMENTAL;
set hoodie.mytableName.consume.max.commits=3;
set hoodie.mytableName.consume.start.timestamp=commitTime;
注意这3个参数是表级别参数
参数名 | 描述 |
---|---|
hoodie.mytableName.consume.mode | Hudi表的查询模式。 增量查询 :INCREMENTAL 非增量查询:不设置或者设为SNAPSHOT |
hoodie.mytableName.consume.start.timestamp | Hudi表增量查询起始时间。 |
hoodie. mytableName.consume.max.commits | Hudi表基于 hoodie.mytableName.consume.start.timestamp 之后要查询的增量commit次数。 例如: 设置为3时,增量查询从指定的起始时间之后commit 3次的数据 设为-1时,增量查询从指定的起始时间之后提交的所有数据 |
COW 表查询
实时视图
设置 hive.input.format 为 org.apache.hadoop.hive.ql.io.HiveInputFormat 或者org.apache.hudi.hadoop.hive.HoodieCombineHiveInputFormat,像普通的hive表一样查询即可:
set hive.input.format= org.apache.hadoop.hive.ql.io.HiveInputFormat;
select count(*) from hudi_cow;
增量视图
除了要设置 hive.input.format
,还需要设置上述的3个增量查询参数,且增量查询语句中的必须添加 where 关键字并将 `_hoodie_commit_time > 'startCommitTime'
作为过滤条件(这地方主要是hudi的小文件合并会把新旧commit的数据合并成新数据,hive是没法直接从parquet文件知道哪些是新数据哪些是老数据)
set hive.input.format= org.apache.hadoop.hive.ql.io.HiveInputFormat;
set hoodie.hudicow.consume.mode= INCREMENTAL;
set hoodie.hudicow.consume.max.commits=3;
set hoodie.hudicow.consume.start.timestamp= xxxx;
select count(*) from hudicow where `_hoodie_commit_time`>'xxxx'
-- (这里注意`_hoodie_commit_time` 的引号是反引号(tab键上面那个)不是单引号, 'xxxx'是单引号)
MOR 表查询
这里假设 MOR 类型 Hudi 源表的表名为hudi_mor,映射为两张 Hive 外部表hudi_mor_ro(ro表)和 hudi_mor_rt(rt表)。
实时视图
设置了 hive.input.format 之后,即可查询到Hudi源表的最新数据
set hive.input.format= org.apache.hadoop.hive.ql.io.HiveInputFormat;
select * from hudicow_rt;
读优化视图
ro 表全称 read oprimized table,对于 MOR 表同步的 xxx_ro 表,只暴露压缩后的 parquet。其查询方式和COW表类似。设置完 hiveInputFormat 之后 和普通的 Hive 表一样查询即可。
增量视图
这个增量查询针对的rt表,不是ro表。同 COW 表的增量查询类似:
set hive.input.format=org.apache.hudi.hadoop.hive.HoodieCombineHiveInputFormat; // 这地方指定为HoodieCombineHiveInputFormat
set hoodie.hudimor.consume.mode=INCREMENTAL;
set hoodie.hudimor.consume.max.commits=-1;
set hoodie.hudimor.consume.start.timestamp=xxxx;
select * from hudimor_rt where `_hoodie_commit_time`>'xxxx';// 这个表名要是rt表
说明:
set hive.input.format=org.apache.hudi.hadoop.hive.HoodieCombineHiveInputFormat;
最好只用于 rt 表的增量查询 当然其他种类的查询也可以设置为这个,这个参数会影响到普通的hive表查询,因此在rt表增量查询完成后,应该设置set hive.input.format=org.apache.hadoop.hive.ql.io.HiveInputFormat;
或者改为默认值set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
用于其他表的查询。set hoodie.mytableName.consume.mode=INCREMENTAL;
仅用于该表的增量查询模式,若要对该表切换为其他查询模式,应设置set hoodie.hudisourcetablename.consume.mode=SNAPSHOT;
当前的一些问题
- Hive读 Hudi 表会将所有的数据给打印出来,这个有严重的性能问题和数据安全问题,请拉去社区的最新分支。
- MOR 表增量视图的读取当前还是有不少问题的请拉取 https://github.com/apache/hudi/pull/3203 这个pr
- MOR 表的实时视图读取,请按需设置
mapreduce.input.fileinputformat.split.maxsize
的大小 禁止hive取切分读取的文件,否则会出现数据重复。这个问题当前是无解 的,Spark 读 Hudi实时视图的时候代码直接写死不会切分文件,Hive需要手动设置。 - 如果碰到 ClassNotFound, NoSuchMethod 等错误请检查 Hive lib库下面的jar包是否出现冲突。
Hive 3.1.0 兼容
Hive 3.1.0 的同学需要稍微改下 Hive 侧源码
修改
org.apache.hadoop.hive.common.FileUtils
函数:public static final PathFilter HIDDEN_FILES_PATH_FILTER = new PathFilter() { @Override public boolean accept(Path p) { String name = p.getName(); boolean isHudiMeta = name.startsWith(".hoodie"); boolean isHudiLog = false; Pattern LOG_FILE_PATTERN = Pattern.compile("\\.(.*)_(.*)\\.(.*)\\.([0-9]*)(_(([0-9]*)-([0-9]*)-([0-9]*)))?"); Matcher matcher = LOG_FILE_PATTERN.matcher(name); if (matcher.find()) { isHudiLog = true; } boolean isHudiFile = isHudiLog || isHudiMeta; return (!name.startsWith("_") && !name.startsWith(".")) || isHudiFile; } };
重新编译 hive, 把新编译的 hive-common-xxx.jar, hive-exec-xxx.jar 替换到 hive server 的 lib 目录下 注意权限和名字和原来的jar包保持一致,重启hive-server。
错误收集和反馈
Hive 错误日志这块简单的提一下,请去 yarn 上取 mr 的详细错误日志,不要把 beeline 上的错误直接贴群里,那个意义不大。 最后大家碰到上问题可以在群里直接反馈,如有复现步骤 请附带进去。
如果是明确的 bug 可以到 HUDI-2649 下提 sub-task。