Hbase 表模型
HBase 中有 Table 和 Family 和 Qualifier 三个概念。
Table 可以直观理解为表,而 Family 和 Qualifier 直观理解为列,一个 Family 下面可以有多个 Qualifier。即可以理解为,HBase 中的列是二级列,其中 Family 是第一级列,Qualifier 是第二级列。两个是父子关系。
Q: 对于传统关系型数据库中的一张 table,在业务转换到 hbase 上建模时,从性能的角度应该如何设置 family 和 qualifier 呢?
A: 最极端的,可以每一列都设置成一个 family,也可以只有一个 family,但所有列都是其中的一个 qualifier,那么有什么区别呢?
family 越多,那么获取每一个 cell 数据的优势越明显,因为 io 和网络都减少了,而如果只有一个 family,那么每一次读都会读取当前 rowkey 的所有数据,网络和 io 上会有一些损失。
当然如果要获取的是固定的几列数据,那么把这几列写到一个 family 中比分别设置 family 要更好,因为只需一次请求就能拿回所有数据。
首先,不同的 family 是在同一个 region 下面。而每一个 family 都会分配一个 memstore,所以更多的 family 会消耗更多的内存。
其次,目前版本的 hbase,在 flush 和 compaction 都是以 region 为单位的,也就是说当一个 family 达到 flush 条件时,该 region 的所有 family 所属的 memstore 都会 flush 一次,即使 memstore 中只有很少的数据也会触发 flush 而生成小文件。这样就增加了 compaction 发生的机率,而 compaction 也是以 region 为单位的,这样就很容易发生 compaction 风暴从而降低系统的整体吞吐量。
第三,由于 hfile 是以 family 为单位的,因此对于多个 family 来说,数据被分散到了更多的 hfile 中,减小了 split 发生的机率。这是把双刃剑。更少的 split 会导致该 region 的体积比较大,由于 balance 是以 region 的数目而不是大小为单位来进行的,因此可能会导致 balance 失效。而从好的方面来说,更少的 split 会让系统提供更加稳定的在线服务。
上述第三点的好处对于在线应用来说是明显的,而坏处我们可以通过在请求的低谷时间进行人工的 split 和 balance 来避免掉。
因此对于写比较多的系统,如果是离线应该,我们尽量只用一个 family 好了,但如果是在线应用,那还是应该根据应用的情况合理地分配 family。
表操作
创建表
create '表名称', '列名称 1','列名称 2','列名称 N'
eg: create 'member','member_id','address','info‘
列出所有的表
list
描述表
describe 'member'
删除表的一个列
- disable 'member'
- alter 'member', {NAME=>'member_id',METHOD=>'delete'}
- enable 'member'
删除一个表
- disable 'member'
- drop 'member'
查询表是否存在
exists 'member'
判断表是否 enable
is_enabled 'member'
判断表是否 disable
is_disabled 'member'
记录
添加记录
put '表名称', '行名称', '列名称:', '值'
put'member','scutshuxue','info:age','24'
put'member','scutshuxue','info:birthday','1987-06-17'
put'member','scutshuxue','info:company','alibaba'
put'member','scutshuxue','address:contry','china'
put'member','scutshuxue','address:province','zhejiang'
put'member','scutshuxue','address:city','hangzhou'
put'member','xiaofeng','info:birthday','1987-4-17'
put'member','xiaofeng','info:favorite','movie'
put'member','xiaofeng','info:company','alibaba'
put'member','xiaofeng','address:contry','china'
put'member','xiaofeng','address:province','guangdong'
put'member','xiaofeng','address:city','jieyang'
put'member','xiaofeng','address:town','xianqiao'
查看记录
get '表名称', '行名称'
获取一个 id 的所有数据
get 'member','scutshuxue'
获取一个 id,一个列族的所有数据
get 'member','scutshuxue','info'
获取一个 id,一个列族中一个列的所有数据
get 'member','scutshuxue','info:age'
通过 timestamp 来获取两个版本的数据
get 'member','scutshuxue',{COLUMN=>'info:age',TIMESTAMP=>1321586238965}
get 'member','scutshuxue',{COLUMN=>'info:age',TIMESTAMP=>1321586571843}
查看表中的记录总数
count '表名称'
count 'member'
删除记录
delete '表名' ,'行名称' , '列名称'
删除 id 为 temp 的值的‘info:age’字段
delete 'member','temp','info:age'
get 'member','temp'
增加递增字段
给‘xiaofeng’这个 id 增加'info:age'字段,并使用 counter 实现递增
incr 'member','xiaofeng','info:age'
get 'member','xiaofeng','info:age'
获取当前 count 的值
get_counter 'member','xiaofeng','info:age'
删除整行
deleteall 'member','xiaofeng'
删除一张表
先要屏蔽该表,才能对该表进行删除
- 第一步 disable '表名称'
- 第二步 drop '表名称'
清空一张表
truncate 'member'
全表扫描
scan "表名称"
scan 'member'
查看某个表某个列中所有数据
scan "表名称" , ['列名称:']
更新记录
重写一遍进行覆盖
put 'member','scutshuxue','info:age' ,'99'
get 'member','scutshuxue','info:age'
查看服务器状态
status
查看版本
version
参考:
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于