轉載:http://lxw1234.com/archives/2015/04/101.htmnode
環境配置:緩存
hadoop-2.0.0-cdh4.3.0 (4 nodes, 24G mem/node)oop
hbase-0.94.6-cdh4.3.0 (4 nodes,maxHeapMB=9973/node)性能
hive-0.10.0-cdh4.3.0設計
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';3d
on_hdfs (20萬記錄,150M,TextFile on HDFS)
on_hbase(20萬記錄,160M,HFile on HDFS)orm
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;
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()來獲取數據;
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數增長。
因此,須要爲少許的RPC請求次數和客戶端以及服務端的內存消耗找到平衡點。
rpc.metrics.next_num_ops
未設置caching,每一個RegionServer上經過next()方法調用RPC的次數峯值達到1000萬:
設置了caching=2000,每一個RegionServer上經過next()方法調用RPC的次數峯值只有4000:
設置了caching以後,幾個RegionServer上的內存消耗明顯增長:
所以,在使用Hive over HBase,對HBase中的表作統計分析時候,須要特別注意如下幾個方面:
1. 對HBase表進行預分配Region,根據表的數據量估算出一個合理的Region數;
2. rowkey設計上須要注意,儘可能使rowkey均勻分佈在預分配的N個Region上;
3. 經過set hbase.client.scanner.caching設置合理的掃描器緩存;
4. 關閉mapreduce的推測執行:
set mapred.map.tasks.speculative.execution = false;set mapred.reduce.tasks.speculative.execution = false;