转载: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;