声明:- 本文基于Centos 6.x + CDH 5.x
- 本例中 Hbase 是安装成集群模式的
本文通过建立student表等相关操作,简单介绍一下hbase的shell操作 建立student 表使用 hbase shell命令进入hbase的命令行 - [root@localhostconf]#hbaseshell
- 2014-08-2216:10:47,662INFO[main]Configuration.deprecation:hadoop.native.libisdeprecated.Instead,useio.native.lib.available
- HBaseShell;enter'help<RETURN>'forlistofsupportedcommands.
- Type"exit<RETURN>"toleavetheHBaseShell
- Version0.96.1.1-cdh5.0.1,rUnknown,TueMay613:27:24PDT2014
然后用 create建立一个表,我们建立的表有如下属性 表名: student 列簇:sid, name, age 什么是列簇?Hbase是面向列存储的数据库。Hbase中数据列是由列簇来组织的。一个列簇相当于你在mysql中这个表的多个列定义的总和。但是特别的是,一个表可以对多个列簇。具体列簇里面有哪些列是开始时不用指定的。暂时只需要知道这么多,等做了以后慢慢去理解消化,我们学习的时候一定要掌握方法,先做再想为什么这么做,是最高效的学习方式。
为什么要有列簇?在同一个列簇中的列是存放在一个实例上的。所以对于列簇的理解我的猜测是这样的,刚开始可能没有列簇。虽然nosql是不用定义列的,但是由于我们的hadoop是分布式的,肯定会有一些列在这台机子上,有一些列在那些机子上,为了性能问题,需要弄出一个算法来把一些经常在一起使用的列放到一台机子上,最简单的算法就是由用户自己去定,这就产生了列簇,也就是列的集合,在同一个列簇中的列都在一个机子上。
说完了概念,我们来建立一下这个表 - hbase(main):001:0>create'student','info'
- 0row(s)in4.3300seconds
- =>Hbase::Table-student
增加数据使用put增加一行,这里说的一行意思是:一个表的一个列簇中的一个行,在mysql中就相当于只增加 一行中的一列 - hbase(main):002:0>put'student','row1','info:name','jack'
- 0row(s)in0.1990seconds
意思是往 student 的 name 列中插入一个值 jack 我们查一下这条数据 - hbase(main):003:0>get'student','row1','info:name'
- COLUMNCELL
- info:nametimestamp=1408697225683,value=jack
- 1row(s)in0.0490seconds
查出来了。 怎么样?是不是感觉这么费劲才插入了一个行的一个列?这是以为hbase是基于google的工程师 Fay Chang (应该是个华裔) 的关于bigtable的论坛写的,而bigtable就是拥有超大列数的表格,大到什么程度?大到一台电脑放不下了,必须用多台电脑分布式的存放,才能放的下,所以数据的操作都是以一行一列为最小单位的。 这个row1 是rowkey rowkey行以rowkey作为唯一标示。Rowkey是一段字节数组,这意味着,任何东西都可以保存进去,例如字符串、或者数字。行是按字典的排序由低到高存储在表中
我们继续插入这行别的列 - hbase(main):004:0>put'student','row1','info:sid','1'
- 0row(s)in0.0200seconds
- hbase(main):005:0>put'student','row1','info:age','22'
- 0row(s)in0.0210seconds
然后我们用scan命令查询一下整个表 - hbase(main):006:0>scan'student'
- ROWCOLUMN+CELL
- row1column=info:age,timestamp=1408697651322,value=22
- row1column=info:name,timestamp=1408697225683,value=jack
- row1column=info:sid,timestamp=1408697640490,value=1
- 1row(s)in0.0580seconds
可以看到有三条记录,但是都是一个row里面的,这个row才是相当于mysql的一行 继续插入别的记录,最终结果是这样 - hbase(main):005:0>scan'student'
- ROWCOLUMN+CELL
- row1column=info:age,timestamp=1420817226790,value=22
- row1column=info:name,timestamp=1420817205836,value=jack
- row1column=info:sid,timestamp=1420817219869,value=1
- row2column=info:age,timestamp=1420817278346,value=28
- row2column=info:name,timestamp=1420817252182,value=terry
- row2column=info:sid,timestamp=1420817267780,value=2
- row3column=info:age,timestamp=1420817315351,value=18
- row3column=info:name,timestamp=1420817294342,value=billy
- row3column=info:sid,timestamp=1420817304621,value=3
- row4column=info:name,timestamp=1420858768667,value=karry
- row4column=info:sid,timestamp=1420858794556,value=4
- 4row(s)in1.0990seconds
命令介绍有了基础数据我们就可以通过一边操作一边学习hbase的命令了,比如上个例子我们学习到了一个新的命令scan scan 查询数据表scan命令如果不带任何参数相当于sql中的 select * from table
Limit 查询后显示的条数用limit可以限制查询的条数 - scan'student',{'LIMIT'=>2}
效果如下 - hbase(main):006:0>scan'student',{'LIMIT'=>2}
- ROWCOLUMN+CELL
- row1column=info:age,timestamp=1420817226790,value=22
- row1column=info:name,timestamp=1420817205836,value=jack
- row1column=info:sid,timestamp=1420817219869,value=1
- row2column=info:age,timestamp=1420817278346,value=28
- row2column=info:name,timestamp=1420817252182,value=terry
- row2column=info:sid,timestamp=1420817267780,value=2
- 2row(s)in0.8250seconds
STARTROW 起点rowkey用startrow可以定义查询返回结果的起点rowkey,相当于大于等于,比如
- hbase(main):007:0>scan'student',{'STARTROW'=>'row2'}
- ROWCOLUMN+CELL
- row2column=info:age,timestamp=1420817278346,value=28
- row2column=info:name,timestamp=1420817252182,value=terry
- row2column=info:sid,timestamp=1420817267780,value=2
- row3column=info:age,timestamp=1420817315351,value=18
- row3column=info:name,timestamp=1420817294342,value=billy
- row3column=info:sid,timestamp=1420817304621,value=3
- row4column=info:name,timestamp=1420858768667,value=karry
- row4column=info:sid,timestamp=1420858794556,value=4
STARTROW 可以使用通配符,比如 - hbase(main):008:0>scan'student',{'STARTROW'=>'row*'}
- ROWCOLUMN+CELL
- row1column=info:age,timestamp=1420817226790,value=22
- row1column=info:name,timestamp=1420817205836,value=jack
- row1column=info:sid,timestamp=1420817219869,value=1
- row2column=info:age,timestamp=1420817278346,value=28
- row2column=info:name,timestamp=1420817252182,value=terry
- row2column=info:sid,timestamp=1420817267780,value=2
- row3column=info:age,timestamp=1420817315351,value=18
- row3column=info:name,timestamp=1420817294342,value=billy
- row3column=info:sid,timestamp=1420817304621,value=3
- row4column=info:name,timestamp=1420858768667,value=karry
- row4column=info:sid,timestamp=1420858794556,value=4
- 4row(s)in0.2830seconds
多个参数可以同时使用,比如我要查询startrow = row2 并且只返回一条 - hbase(main):009:0>scan'student',{'STARTROW'=>'row2','LIMIT'=>1}
- ROWCOLUMN+CELL
- row2column=info:age,timestamp=1420817278346,value=28
- row2column=info:name,timestamp=1420817252182,value=terry
- row2column=info:sid,timestamp=1420817267780,value=2
- 1row(s)in0.1890seconds
STOPROW 定义查询的结束rowkey跟startrow类似,同上
COLUMNS 控制返回的字段列表就相当于sql中的 select xx,xxx,xxx from 这里面的列定义。比如我只需要查询所有学生的名字和年龄,不需要sid信息 - hbase(main):011:0>scan'student',{'COLUMNS'=>['info:name','info:age'],LIMIT=>3}
- ROWCOLUMN+CELL
- row1column=info:age,timestamp=1420817226790,value=22
- row1column=info:name,timestamp=1420817205836,value=jack
- row2column=info:age,timestamp=1420817278346,value=28
- row2column=info:name,timestamp=1420817252182,value=terry
- row3column=info:age,timestamp=1420817315351,value=18
- row3column=info:name,timestamp=1420817294342,value=billy
- 3row(s)in0.4470seconds
注意写列名的时候要记得带上列簇!比如 info:name
TIMESTAMP 使用时间来精确定位数据timestamp可以精确的指定某一条记录 - hbase(main):012:0>scan'student',{'TIMESTAMP'=>1420817315351}
- ROWCOLUMN+CELL
- row3column=info:age,timestamp=1420817315351,value=18
- 1row(s)in0.1920seconds
get 获取一行数据用get可以只获取一行数据 - hbase(main):073:0>get'student','row1'
- COLUMNCELL
- info:agetimestamp=1420817226790,value=22
- info:nametimestamp=1420817205836,value=jack
- info:sidtimestamp=1420817219869,value=1
- 3row(s)in0.1730seconds
可以跟上更复杂的参数 - hbase(main):076:0>get'student','row1',{COLUMN=>['info:name','info:sid']}
- COLUMNCELL
- info:nametimestamp=1420817205836,value=jack
- info:sidtimestamp=1420817219869,value=1
- 2row(s)in0.0490seconds
- hbase(main):077:0>get'student','row1',{COLUMN=>['info:name','info:sid'],TIMESTAMP=>1420817219869,VERSION=>1}
- COLUMNCELL
- info:sidtimestamp=1420817219869,value=1
- 1row(s)in0.0740seconds
describe 查看表信息describe 可以查看表的信息,这个命令会常常用到 - hbase(main):013:0>describe'student'
- DESCRIPTIONENABLED
- 'student',{NAME=>'info',DATA_BLOCK_ENCODING=>'NONE',BLOOMFILTER=>'ROW',true
- REPLICATION_SCOPE=>'0',VERSIONS=>'1',COMPRESSION=>'NONE',MIN_VERSIONS
- =>'0',TTL=>'FOREVER',KEEP_DELETED_CELLS=>'false',BLOCKSIZE=>'65536',I
- N_MEMORY=>'false',BLOCKCACHE=>'true'}
- 1row(s)in7.6720seconds
alter 修改表的列簇用alter可以修改表的列簇,hbase的一个表其实全部信息就是列簇的信息了,比如我们可以增加一个列簇f2 - alter'student',{NAME=>'f2',VERSION=>2}
这个VERSION官方说是每个字段可以有2个版本,就是一个行的一个列元素可以存成两个值,拥有不同的version 添加完再看下表结构 - hbase(main):057:0>describe'student'
- DESCRIPTIONENABLED
- 'student',{NAME=>'f2',DATA_BLOCK_ENCODING=>'NONE',BLOOMFILTER=>'ROW',Rtrue
- EPLICATION_SCOPE=>'0',COMPRESSION=>'NONE',VERSIONS=>'1',TTL=>'FOREVER
- ',MIN_VERSIONS=>'0',KEEP_DELETED_CELLS=>'false',BLOCKSIZE=>'65536',IN_
- MEMORY=>'false',BLOCKCACHE=>'true'},{NAME=>'info',DATA_BLOCK_ENCODING=
- >'NONE',BLOOMFILTER=>'ROW',REPLICATION_SCOPE=>'0',VERSIONS=>'1',COMPR
- ESSION=>'NONE',MIN_VERSIONS=>'0',TTL=>'FOREVER',KEEP_DELETED_CELLS=>'
- false',BLOCKSIZE=>'65536',IN_MEMORY=>'false',BLOCKCACHE=>'true'}
- 1row(s)in0.6180seconds
可以看到有两个列簇,一个是f2,一个是info
用 TTL 控制表的数据自动过期不过我这边用一个比较实用的例子来教大家操作alter:在实际生产环境上经常需要给表增加过期时间,方便表自动清理早期的数据,防止数据过多,毕竟能用hadoop的环境数据量那都是“海量” 现在我把f2这个列簇的TTL修改为20秒 - alter'student',{NAME=>'f2',TTL=>20}
然后再看下表信息 - hbase(main):061:0>describe'student'
- DESCRIPTIONENABLED
- 'student',{NAME=>'f2',DATA_BLOCK_ENCODING=>'NONE',BLOOMFILTER=>'ROW',Rtrue
- EPLICATION_SCOPE=>'0',COMPRESSION=>'NONE',VERSIONS=>'1',TTL=>'20SECO
- NDS',MIN_VERSIONS=>'0',KEEP_DELETED_CELLS=>'false',BLOCKSIZE=>'65536',
- IN_MEMORY=>'false',BLOCKCACHE=>'true'},{NAME=>'info',DATA_BLOCK_ENCODIN
- G=>'NONE',BLOOMFILTER=>'ROW',REPLICATION_SCOPE=>'0',VERSIONS=>'1',CO
- MPRESSION=>'NONE',MIN_VERSIONS=>'0',TTL=>'FOREVER',KEEP_DELETED_CELLS=
- >'false',BLOCKSIZE=>'65536',IN_MEMORY=>'false',BLOCKCACHE=>'true'}
- 1row(s)in0.1540seconds
可以看到f2的 TTL 被设置为20 seconds。 然后我们测试一下添加一个记录到f2去,然后等20秒再去看下 - hbase(main):065:0>put'student','row3','f2:grade','2'
- 0row(s)in0.0650seconds
- hbase(main):066:0>scan'student',{STARTROW=>'row3',LIMIT=>1}
- ROWCOLUMN+CELL
- row3column=f2:grade,timestamp=1420872179176,value=2
- row3column=info:age,timestamp=1420817315351,value=18
- row3column=info:name,timestamp=1420817294342,value=billy
- row3column=info:sid,timestamp=1420817304621,value=3
- 1row(s)in0.0630seconds
- hbase(main):067:0>scan'student',{STARTROW=>'row3',LIMIT=>1}
- ROWCOLUMN+CELL
- row3column=info:age,timestamp=1420817315351,value=18
- row3column=info:name,timestamp=1420817294342,value=billy
- row3column=info:sid,timestamp=1420817304621,value=3
- 1row(s)in0.1370seconds
会看到刚添加进去的时候row2还有 f2:grade的数据,但是过了一会儿去看就没了
使用alter删除列簇使用alter删除列簇的操作是带上一个METHOD参数,并写值为 delete - hbase(main):068:0>alter'student',{NAME=>'f2',METHOD=>'delete'}
- Updatingallregionswiththenewschema...
- 0/1regionsupdated.
- 1/1regionsupdated.
- Done.
- 0row(s)in3.9750seconds
- hbase(main):069:0>describe'student'
- DESCRIPTIONENABLED
- 'student',{NAME=>'info',DATA_BLOCK_ENCODING=>'NONE',BLOOMFILTER=>'ROW',true
- REPLICATION_SCOPE=>'0',VERSIONS=>'1',COMPRESSION=>'NONE',MIN_VERSIONS
- =>'0',TTL=>'FOREVER',KEEP_DELETED_CELLS=>'false',BLOCKSIZE=>'65536',I
- N_MEMORY=>'false',BLOCKCACHE=>'true'}
- 1row(s)in0.2210seconds
count 统计表中的数据跟传统的关系型数据库不一样,这个命令可能会执行很久 - hbase(main):082:0>count'student'
- 4row(s)in0.6410seconds
- =>4
这个命令还有一个很奇怪的功能,就是在统计的时候可以每隔X行显示一下数据的rowkey,可能是方便统计的时候看下统计到哪里了,比如我分别用间隔2行跟间隔1行做了实验 - hbase(main):083:0>count'student',2
- Currentcount:2,row:row2
- Currentcount:4,row:row4
- 4row(s)in0.0480seconds
- =>4
- hbase(main):084:0>count'student',1
- Currentcount:1,row:row1
- Currentcount:2,row:row2
- Currentcount:3,row:row3
- Currentcount:4,row:row4
- 4row(s)in0.0650seconds
- =>4
用list可以列出当前hbase中的所有表 - hbase(main):079:0>list
- TABLE
- employee
- employee2
- student
- 3row(s)in0.2020seconds
- =>["employee","employee2","student"]
status 命令查询服务状态 - hbase(main):013:0>status
- 1servers,0dead,3.0000averageload
- hbase(main):070:0>list
- TABLE
- employee
- employee2
- student
- 3row(s)in0.6380seconds
- =>["employee","employee2","student"]
version查询版本号 whoami看连接用户 - hbase(main):014:0>whoami
- root(auth:SIMPLE)
truncate 快速清除数据跟一般数据库中的truncate不太一样,如果你执行 truncate,hbase就是帮你把表停掉,删掉再重建一次,只是这个动作不用你手动做了而已 - hbase(main):086:0>truncate'student'
- Truncating'student'table(itmaytakeawhile):
- -Disablingtable...
- -Droppingtable...
- -Creatingtable...
- 0row(s)in4.6330seconds
主要的命令就介绍到这里,更详细的命令参考http://wiki.apache.org/hadoop/Hbase/Shell
参考资料- http://wiki.apache.org/hadoop/Hbase/Shell
|