HBase Shell操作
封面画师:画师JW 封面ID:79686153
HBase简介
HBase是一种分布性、可扩展、支持海量数据存储的NoSQL数据库。
HBase的数据模型
逻辑上,HBase的数据模型同关系型数据库类型,数据存储在一张表类,有行有列。但从HBase的底层物理存储结构(K-V)来看,HBase更像一个multi-dimensional map。
表结构(HBase逻辑结构):
参考资料:HBase数据模型介绍
高表行多,宽表列多。
Region是一张表的切片,而且是横向切片,相当于对宽表的切分。
store是真正存储的内容。
HBase物理存储结构:
如果需要在Windows和Linux上测试HBase,由于时间戳的关系,请保证这两个系统的时间是一致的。当你查询某个列时,HBase会返回时间戳较大的列的数据。
数据模型
Name Space
命名空间,类似于关系型数据库的database概念,每个命名空间下有多个表,HBase有两个自带的命名空间,分别是hbase和default,hbase中存放的是HBase内置的表,default是用户默认使用的命名空间。
Region
类似于关系型数据库的表概念。不同的是,HBase定义表时只需要声明列族即可,不需要声明具体的列。这意味着,往HBase写入数据时,字段可以动态、按需指定。因此,和关系型数据库相比,HBase能够轻松应对字段变更的场景。
表的切片。当数据不多时,表和Region是一一对应的关系,一个表就是一个Region;当数据量大起来时,一个表就会被切分成多个Region。除了系统自动帮我们切分,我们也可以进行手动切分。
HBase中的列名相当于HBase中的数据。
Row
HBase表中的每行数据都是由一个RowKey和多个Column(列)组成,数据是按照RowKey的字典顺序存储的,并且查询数据时只能根据RowKey进行检索,所以RowKey的设计十分重要。
因此我们查询数据时,除了可以全局扫描,还可以范围扫描。
Column
HBase中的每个列都是有Column Family(列族)和Column Qualifier(列限定符)进行限定,例如:info:name , info:age 。建表时,只需指名列族,而列限定符无需预先定义。
Time Stamp
用于标识数据的不同版本(version),每条数据写入时,如果不指定时间戳,系统会自动为其加上该字段,其值为写入HBase的时间。
Cell
由{RowKey, column Family: column Qualifier, time stamp}唯一确定单元。cell中的数据是没有类型的,全部是字节码形式存储。
基础架构
当HMaster节点挂掉后,做数据级别(表内数据)的增删改查是没问题的,但是做表级别的是不行的。
RegionServer的作用:(DML)
Data:get、put、delete
Region:splitRegion、compactRegion
Master的作用:(DDL)
Table:create、delete、alter
RegionServer:分配regions到每个RegionServer,监控每个RegionServer的状态。
HBase的安装
已单独写成笔记文档。
HBase Shell操作
基本操作
进入HBase客户端命令行:
1 | [root@db06 mofan]# bin/hbase shell |
查看帮助命令:
1 | Hbase(mian):001:0> help |
查看当前数据库中 有哪些表:
1 | Hbase(mian):002:0> list |
DDL
创建表:
创建表时,必须指定至少一个列族。
1 | hbase(main):002:0> create 'student','info' |
查看表具体信息:
1 | hbase(main):004:0> desc 'student' |
变更表信息(版本号):
1 | hbase(main):009:0> alter 'student', {NAME=>'info',VERSIONS=>3} |
删除表:
1 | hbase(main):011:0> disable 'student' |
我们在删除表时,必须先disable表,即:表在可用状态(enable)下不能被删除,需要删除得将其设置成不可用状态(disable)。
查看当前所有命名空间:
1 | hbase(main):014:0> list_namespace |
创建命名空间:
1 | hbase(main):015:0> create_namespace 'bigdata' |
在指定的命名空间下创建一个表:
1 | hbase(main):017:0> create 'bigdata:stu',"info" |
删除命名空间:
1 | hbase(main):019:0> disable 'bigdata:stu' |
删除命名空间时,不许保证当前命名空间为空。
DML
增加 & 查询
向指定表内插入数据:
1 | hbase(main):024:0> put 'stu','1001','info1:name','mofan' |
解析:向stu表中插入数据,RowKey:1001,列族info1下的name列,插入值:mofan
查询表内所有数据:
1 | hbase(main):025:0> scan 'stu' |
我们查询出来的数据是按照RowKey的字典顺序进行升序排序的,这很重要!
查询表中指定条件的数据:
1 | hbase(main):026:0> get 'stu','1001' |
解析:查询stu表内,RowKey为1001的数据
我们先插入几条数据备用:
1 | hbase(main):027:0> put 'stu','1001','info1:sex','male' |
1 | hbase(main):035:0> get 'stu','1001','info1:name' |
解析:查询stu表内,RowKey为1001,列族info1下的name列的所有数据
1 | hbase(main):037:0> get 'stu','1001','info1' |
解析:查询stu表内,RowKey为1001,列族info1下的所有数据
使用scan进行范围扫描查询:
1 | hbase(main):039:0> scan 'stu',{STARTROW=>'1001',STOPROW=>'1003'} |
解析:查询stu表中,RowKey大于等于1001,小于1003的数据。 [1001,1003),左闭右开。 我们在进行查询的时候,也可以只指定STARTROW或STOPROW。
使用过滤器查询参考链接:HBase基础之常用过滤器hbase shell操作
修改 & 删除
修改指定单元格的数据:
1 | hbase(main):003:0> put 'stu','1001','info1:name','zhangsan' |
解析:将stu表中,RowKey为1001,info1列族下的name列的数据改为zhangsan。因为是修改数据,因此必须要有原数据才可修改,否则就是增加数据或报错。
数据修改后,并不是立即在HBase中删除,它会修改数据版本,高版本的数据会覆盖低版本的数据,相当于一种软删除,我们可以用下列方式查询10个版本以内的指定数据表内的所有数据:
1 | hbase(main):006:0> scan 'stu',{RAW=>true,VERSIONS=>10} |
我们可以在插入数据时,指定数据的时间戳,然后我们再查询的时候就只会返回时间戳最大的数据。
1 | hbase(main):007:0> put 'stu','1001','info1:name','wangwu',1588693216333 |
1588693216333为指定的时间戳,进行操作时,请将这里的时间戳设置为mofan之后,zhangsan之前。如果你是根据我一步步完成了命令的,现在进行查询stu表中的数据,得到的返回结果是张三。
结果示例:
1 | ROW COLUMN+CELL |
正是因为这个原因,我们在Windows和Linux进行HBase相关的操作时,请务必保证两个系统的时间是一致的。
删除指定单元格的数据:
1 | hbase(main):010:0> delete 'stu','1001','info1:sex' |
解析:删除stu表中,RowKey为1001,info1列族下sex列的数据。
使用delete删除数据时,如果此单元格有低版本的数据,那么查询数据时,会返回该单元格低版本的数据,而不是自己将该单元格所有版本数据全部删除。
我们可以查询表中10个版本以内的数据,得到如下结果:
1 | 1001 column=info1:name, timestamp=1588733177444, type=Delete |
我们发现刚刚删除的单元格的type变成了Delete,然后我们查询数据,我们又会发现,返回的是wangwu,而不是一条数据都没,这也验证了我们的结论。
删除单元格内所有版本的数据:
1 | hbase(main):022:0> deleteall 'stu','1001','info1:name' |
解析:删除stu表中,RowKey为1001,info1列族下sex列的所有版本数据。
如果这时我们再查询数据,我们无法查看到name列下的数据。我们查询表中10个版本以内的数据,得到如下结果:
1 | 1001 column=info1:name, timestamp=1588735280872, type=DeleteColumn |
删除的单元格的type变成了DeleteColumn,当单元格类型为DeleteColumn时,查询数据不会返回低版本数据。
根据时间戳删除数据:
先插入一条数据,再进行删除:
1 | hbase(main):004:0> put 'stu','1001','info1:name','zhaoliu' |
我们使用scan查询这条数据:
1 | 1001 column=info1:name, timestamp=1588744342719, value=zhaoliu |
根据时间戳删除:
1 | hbase(main):007:0> delete 'stu','1001','info1:name',1588744342718 |
注意:我们这里使用的时间戳比查询出的小1,我们测试能否删除成功。执行操作后我们可以发现,并没有删除成功。那么我们让两个时间戳相等再进行一次删除:
1 | hbase(main):007:0> delete 'stu','1001','info1:name',1588744342719 |
执行操作后,我们发现时间戳为1588744342719的数据的type已经变成了Delete,证明删除成功。
测试根据列族进行删除:
1 | hbase(main):014:0> delete 'stu','1002','info1' |
虽然显示运行成功,但是我们查询数据后发现并没有被删除。
1 | 1002 column=info1:, timestamp=1588745457853, type=Delete |
根据RowKey进行删除:
我们删除RowKey为1001的数据,因为数据不够,我们先插入一条再进行删除:
1 | hbase(main):023:0> put 'stu','1001','info1:sex','female' |
清空整个表的数据:
1 | hbase(main):029:0> truncate 'stu' |
解析:清空stu整个表的数据。
DML (多版本)
测试一
由于我们刚清空了stu表,我们先往stu表中put两条数据:
1 | hbase(main):032:0> put 'stu','1005','info1:name','zhangsan' |
然后我们进行版本查询:
1 | hbase(main):036:0> get 'stu','1005',{COLUMN=>'info1:name',VERSIONS=>3} |
查询结果:
1 | COLUMN CELL |
我们发现,尽管进行了版本查询,但结果只返回了一条数据。这是因为我们的stu表只能存储1个版本,因此查询时只返回了时间戳大的版本。
测试二
我们新建一个表进行测试:
1 | hbase(main):002:0> create 'stu2','info' |
插入数据:
1 | hbase(main):005:0> put 'stu2','1005','info:name','zhangsan' |
设置info列族可存储2个版本数据:
1 | hbase(main):007:0> alter 'stu2',{NAME=>'info',VERSIONS=>2} |
进行版本查询:
1 | hbase(main):009:0> get 'stu2','1005',{COLUMN=>'info:name',VERSIONS=>3} |
这时候我们发现数据依然只有一条(wangwu),是因为我们先put了数据,才进行版本设置。我们需要先进行版本设置,再put数据。
再次插入数据:
1 | hbase(main):012:0> put 'stu2','1001','info:name','zhaoliu' |
进行版本查询:
1 | hbase(main):015:0> get 'stu2','1001',{COLUMN=>'info:name',VERSIONS=>3} |
这时候我们发现查询的数据就有两条了(zhaoliu、sunqi)。
那么我们再向stu表,RowKey为1001,info列族中name列中插入一条数据:
1 | hbase(main):016:0> put 'stu2','1001','info:name','zhouba' |
再进行版本查询:
1 | hbase(main):017:0> get 'stu2','1001',{COLUMN=>'info:name',VERSIONS=>3} |
查询出来的数据依旧只有2条(zhaoba、sunqi),虽然我们查找了3个版本的数据,但我们设置了info列数只能存储两个版本的数据。
删除
在Shell模式下,如果我们在允许多个版本数据存在的表里对数据进行删除,会直接删除指定的所有版本数据,无法做到选择删除。