【笔记】关于HBase的总结和疑问
1.HBase和HDFS的异同
2.HBase按列存储
- 数据是按列存储的,每一列单独存放
- 数据即是索引
- 只访问查询涉及到的列,降低I/O
- 每一列由一个线索来处理-查询的并发处理
- 数据类型一致-高效压缩
3.HBase VS HFile
4.HBase查询比Hive快的原因
(1) Hive
- hive是基于mapreduce来处理数据,离线计算速度慢
- mapreduce处理数是基于行的模式,查询数据默认是扫描整个表
- hive中的表是纯逻辑表,本身不存储数据,完全依赖hdfs和mapreduce
(2)HBase
- hbase是物理表,有独立的物理结构,查询的时候将相应的数据加载到内存,提升后续的查询效率
- hbase是基于列存储的,查询的时候可以只扫描某一个或某几个列,避免扫描所有数据
- hbase有一级索引,查询速度非常快
- hbase提供了一个超大的内存hash表,搜索引擎通过这个hash表存储索引,提升查询效率。
5.HBase热点问题
HBase中的行是按照rowkey的字典顺序排序的,然而这种设计却是热点产生的源头。client大量直接的访问集群中的一个或少数几个节点(读或者写等其它操作),大量访问会使热点region所在的单个机器超出自身承受能力,引起性能下降甚region不可用。
产生原因
HBase创建表默认只有一个分区
rowkey设计不合理解决方案
HBase创建表时指定分区
合理设计rowkey常见避免热点的方法
(1) 加盐 : 在rowkey的前面增加随机数,比如:
foo0001 –>a-foo0001
foo0002 –>b-foo0002
foo0001 –>c-foo0001
增加了读写的代价
(2) 哈希:在rowkey的前面增加唯一固定的前缀,比如:
foo0001 –>a-foo0001
foo0002 –>a-foo0002
foo0003 –>a-foo0001保证他们永远在同一个region
增加了写的吞吐量,读可测
(3)反转:反转固定长度或者数字格式的rowkey,比如:
158xxxx6691–>1966xxxx851
牺牲了rowkey的有序性
(4)时间戳(timestamp)反转:
比如需要保存一个用户的操作记录,按照操作时间倒序排序,在设 计rowkey的时候,可以这样设计 [userId反转][Long.Max_Value - timestamp],在查询用户的所有操作记录数据的时候,直接指定反转后的userId,startRow是[userId反转][000000000000],stopRow是[userId反转][Long.Max_Value - timestamp]
如果需要查询某段时间的操作记录,startRow是[user反转][Long.Max_Value - 起始时间],stopRow是[userId反转][Long.Max_Value - 结束时间]
6.rowkey设计成定长的原因
(1) HFile文件中是按照key-value存储数据的,作为key的rowkey,如果过长,占用字节过多,会影响HFile的存储效率。
(2) MenStore将缓存部分数据到内存,rowkey过长,内存的有效利用率将降低,会降低检索效率。
(3) 目前操作系统都是64位,内存8字节对齐,控制在16个字节恰好是8的整数倍。