Apache Hudi 與 Hive 整合手冊

leesf發表於2021-12-12

1. Hudi表對應的Hive外部表介紹

Hudi源表對應一份HDFS資料,可以通過Spark,Flink 元件或者Hudi客戶端將Hudi表的資料對映為Hive外部表,基於該外部表, Hive可以方便的進行實時檢視,讀優化檢視以及增量檢視的查詢。

2. Hive對Hudi的整合

這裡以Hive3.1.1、 Hudi 0.9.0為例, 其他版本類似

  • 將hudi-hadoop-mr-bundle-0.9.0xxx.jar , hudi-hive-sync-bundle-0.9.0xx.jar 放到hiveserver 節點的lib目錄下

  • 修改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>
    
  • 配置完後重啟hive-server

  • 對於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 按上述步驟新增進去。

3. 建立Hudi表對應的hive外部表

一般來說Hudi表在用Spark或者Flink寫入資料時會自動同步到Hive外部表, 此時可以直接通過beeline查詢同步的外部表, 若寫入引擎沒有開啟自動同步,則需要手動利用hudi客戶端工具run_hive_sync_tool.sh 進行同步具體可以參考官網檢視相關引數。

4. 查詢Hudi表對應的Hive外部表

4.1 操作前提

使用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時,增量查詢從指定的起始時間之後提交的所有資料

4.2 COW型別Hudi表的查詢

例如Hudi原表表名為hudicow,同步給hive之後hive表名hudicow

4.2.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 hudicow;

4.2.2 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'是單引號

4.3 MOR型別Hudi表的查詢

例如mor型別Hudi源表的表名為hudimor,對映為兩張Hive外部表hudimor_ro(ro表)和hudimor_rt(rt表)

4.3.1 MOR表讀優化檢視

實際上就是讀 ro表,和cow表類似設定完hiveInputFormat 之後 和普通的hive表一樣查詢即可。

4.3.2 MOR表實時檢視

設定了hive.input.format之後,即可查詢到Hudi源表的最新資料

set hive.input.format = org.apache.hadoop.hive.ql.io.HiveInputFormat;
select * from hudicow_rt;

4.3.3 MOR表增量查詢

這個增量查詢針對的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;

當前Hudi(0.9.0)對接Hive的一些問題,請使用master分支或即將釋出的0.10.0版本

  • hive讀hudi表會將所有的資料給列印出來有嚴重的效能問題和資料安全問題。

  • MOR表的實時檢視讀取 請按需設定mapreduce.input.fileinputformat.split.maxsize的大小 禁止hive取切分讀取的檔案,否則會出現資料重複。這個問題當前是無解的,spark讀hudi實時檢視的時候程式碼直接寫死不會切分檔案,hive需要手動設定。

  • 如果碰到classNotFound, noSuchMethod等錯誤請檢查hive lib庫下面的jar包是否出現衝突。

5. Hive側原始碼修改

為支援Hive查詢Hudi的純log檔案需要對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即可。

相關文章