Hive和HBase的整合原理
Point 1:
配置 hive 與 hbase 整合的目的是利用 HQL 語法實現對 hbase 資料庫的增刪改查操作,基本原理就是利用兩者本身對外的API介面互相進行通訊,兩者通訊主要是依靠hive_hbase-handler.jar工具類。 但請注意:使用Hive操作HBase中的表,只是提供了便捷性,hiveQL引擎使用的是MapReduce,對於效能上,表現比較糟糕,在實際應用過程中可針對不同的場景酌情使用。
Point 2:
1、 將ETL操作的資料存入HBase
2、 HBase作為Hive的資料來源
3、構建低延時的資料倉庫
Point 3:查詢效能比較
query1:
select count(1) from on_hdfs;
select count(1) from on_hbase;
query2(根據key過濾)
select * from on_hdfs
where key = ‘13400000064_1388056783_460095106148962′;
select * from on_hbase
where key = ‘13400000064_1388056783_460095106148962′;
query3(根據value過濾)
select * from on_hdfs where value = ‘XXX';
select * from on_hbase where value = ‘XXX';
on_hdfs (20萬記錄,150M,TextFile on HDFS)
on_hbase(20萬記錄,160M,HFile on HDFS)
on_hdfs (2500萬記錄,2.7G,TextFile on HDFS)
on_hbase(2500萬記錄,3G,HFile on HDFS)
從上圖可以看出,
對於全表掃描,hive_on_hbase查詢時候如果不設定catching,效能遠遠不及hive_on_hdfs;
根據rowkey過濾,hive_on_hbase效能上略好於hive_on_hdfs,特別是資料量大的時候;
設定了caching之後,儘管比不設caching好很多,但還是略遜於hive_on_hdfs;
Point 4:Hive over HBase 原理
Hive與HBase利用兩者本身對外的API來實現整合,主要是靠HBaseStorageHandler進行通訊,利用 HBaseStorageHandler,Hive可以獲取到Hive表對應的HBase表名,列簇以及列,InputFormat和 OutputFormat類,建立和刪除HBase表等。
Hive訪問HBase中表資料,實質上是通過MapReduce讀取HBase表資料,其實現是在MR中,使用HiveHBaseTableInputFormat完成對HBase表的切分,獲取RecordReader物件來讀取資料。
對HBase表的切分原則是一個Region切分成一個Split,即表中有多少個Regions,MR中就有多少個Map;
讀取HBase表資料都是通過構建Scanner,對錶進行全表掃描,如果有過濾條件,則轉化為Filter。當過濾條件為rowkey時,則轉化為對rowkey的過濾;
Scanner通過RPC呼叫RegionServer的next()來獲取資料;
Point 5:效能瓶頸分析
1、 Map Task
Hive讀取HBase表,通過MR,最終使用HiveHBaseTableInputFormat來讀取資料,在getSplit()方法中對 HBase表進行切分,切分原則是根據該表對應的HRegion,將每一個Region作為一個InputSplit,即,該表有多少個Region,就 有多少個Map Task;
每個Region的大小由引數hbase.hregion.max.filesize控制,預設10G,這樣會使得每個map task處理的資料檔案太大,map task效能自然很差;
為HBase表預分配Region,使得每個Region的大小在合理的範圍;
下圖是給該表預分配了15個Region,並且控制key均勻分佈在每個Region上之後,查詢的耗時對比,其本質上是Map數增加。
2、Scan RPC 呼叫:
在Scan中的每一次next()方法都會為每一行資料生成一個單獨的RPC請求, query1和query3中,全表有2500萬行記錄,因此要2500萬次RPC請求;
掃描器快取(Scanner Caching):HBase為掃描器提供了快取的功能,可以通過引數hbase.client.scanner.caching來設定;預設是1;快取 的原理是通過設定一個快取的行數,當客戶端通過RPC請求RegionServer獲取資料時,RegionServer先將資料快取到記憶體,當快取的數 據行數達到引數設定的數量時,再一起返回給客戶端。這樣,通過設定掃描器快取,就可以大幅度減少客戶端RPC呼叫RegionServer的次數;但並不 是快取設定的越大越好,如果設定的太大,每一次RPC呼叫將會佔用更長的時間,因為要獲取更多的資料並傳輸到客戶端,如果返回給客戶端的資料超出了其堆的 大小,程式就會終止並跑出OOM異常;
所以,需要為少量的RPC請求次數和客戶端以及服務端的記憶體消耗找到平衡點。
rpc.metrics.next_num_ops
未設定caching,每個RegionServer上通過next()方法呼叫RPC的次數峰值達到1000萬:
設定了caching=2000,每個RegionServer上通過next()方法呼叫RPC的次數峰值只有4000:
設定了caching之後,幾個RegionServer上的記憶體消耗明顯增加:
掃描器批量(Scanner Batch):快取是面向行一級的操作,而批量則是面向列一級的操作。批量可以控制每一次next()操作要取回多少列。比如,在掃描器中設定setBatch(5),則一次next()返回的Result例項會包括5列。
RPC請求次數的計算公式如下:
RPC請求次數 =
(錶行數 * 每行的列數)/ Min(每行的列數,批量大小) / 掃描器快取
因此,在使用Hive over HBase,對HBase中的表做統計分析時候,需要特別注意以下幾個方面:
對HBase表進行預分配Region,根據表的資料量估算出一個合理的Region數;
rowkey設計上需要注意,儘量使rowkey均勻分佈在預分配的N個Region上;
通過set hbase.client.scanner.caching設定合理的掃描器快取;
關閉mapreduce的推測執行:
set mapred.map.tasks.speculative.execution = false;
set mapred.reduce.tasks.speculative.execution = false;