Hbase的基本语法
Hbase是一个面向列的非关系型数据库,采取Column Family(常译为列族/列簇)来对数据进行分类。
一个列族包含多个列,一个列族的多个列之间通常也具有某种关系,比如相似或同种类别。所以列族可以看作是某种分类(归类)。
每个类别里都会有具体的信息,它们就相当于一个个标识符(变量名),在Hbase中叫做Column Qualifier(列修饰符),列修饰符位于列族里面用来标识一条条数据。
在Hbase中一个列族(Column Family)和一个列修饰符(Column Qualifier)组合起来才叫一个列(Column),使用冒号 : 分割,即 列族:列修饰符。
在传统数据库中每一行的唯一标识符叫做主键,在Hbase中叫做row key(行键);数据在进入Hbase时都会被打上一个时间戳,这个时间戳可以作为版本号来使用。
一个行键、列族、列修饰符、数据和时间戳组合起来叫做一个单元格(Cell)。这里的行键、列族、列修饰符和时间戳其实可以看作是定位属性(类似坐标),最终确定了一个数据。
HBase里边也有表、行和列的概念。
表没什么好说的,就是一张表 ,
一行数据由一个行键和一个或多个相关的列以及它的值所组成
好了,现在比较抽象了。在HBase里边,定位一行数据会有一个唯一的值,这个叫做行键(RowKey)。而在HBase的列不是我们在关系型数据库所想象中的列。
HBase的列(Column)都得归属到列族(Column Family)中。在HBase中用列修饰符(Column Qualifier)来标识每个列。
在HBase里边,先有列族,后有列。
什么是列族?可以简单理解为:列的属性类别
什么是列修饰符?先有列族后有列,在列族下用列修饰符来标识一列
HBase表的每一行中,列的组成都是灵活的,行与行之间的列不需要相同。
换句话说:一个列族下可以任意添加列,不受任何限制
数据写到HBase的时候都会被记录一个时间戳,这个时间戳被我们当做一个版本。比如说,我们修改或者删除某一条的时候,本质上是往里边新增一条数据,记录的版本加一了而已。
现在要把这条记录的值改为40,实际上就是多添加一条记录,在读的时候按照时间戳读最新的记录。所以看起来就是把这条记录改了。
区域Region
Table在行的方向上分割为多个Region。
Region是按大小分割的,每个表开始只有一个region,随着数据的增多,region不断增大,当增大到一个阀值的时候,region就会等分为两个新的region,之后会有越来越多的region。
Region是HBase中分布式存储和负载均衡的最小单元。不同的Region分布到不同的RegionServer上。
Region由一个或者多个Store组成, 每个Store保存一个column family, 每个Store又由一个MemStore(存储在内存中)和0到多个StoreFile(存储在HDFS上)组成.
存储单元 cell
我们外观看到的每个单元格其实都对应着多个存储单元,默认情况下一个单元格对应着一个存储单元,一个存储单元可以存储一份数据,如果一个单元格有多个存储单元就表示一个单元格可以存储多个值。可以通过version来设置存储单元个数。可以通过rowKey + columnFamily + column + timestamp来唯一确定一个存储单元。cell中的数据是没有类型的,全部是字节码形式存贮。
hbase按照时间戳降序排列各时间版本,其他映射建按照升序排序。
hbase shell命令操作
进入hbase 操作界面
hbase shell
查看有哪些表
list
创建表
create ‘表名’, ‘列族名1’, ‘列族名2’, ‘列族名N’
create ‘test’,{NAME => ‘a1’, VERSIONS => 2},{NAME => ‘a2’, VERSIONS => 2}
添加列族 alter
alter ‘表名’, ‘列族名
alter ‘test’,‘userinfo’
删除列族
alter’表名’, {NAME=> ‘列族名’, METHOD=> ‘delete}
alter ‘test’,{NAME=> ‘userinfo’, METHOD=> ‘delete}
删除表
先关闭 disable ‘表’ ,在 drop ‘表’
disable 'test’
drop 'test’
查看表的结构
describe 'test’
查看表所有数据 scan
scan 'test’
查看单个列族
scan ‘test’ ,{COLUMN=>‘userinfo’}
获取某一行数据 get
get ‘test’,'1’
获取某一行列族数据
get ‘test’,‘1’,'userinfo’
Filter过滤器
显示hbase所支持的所有过滤器show_filters
过滤器用于get和scan命令中作为筛选数据的条件,类型关系型数据库中的where的作用
获取rowKey=r1 中的列值等于v2的所有列
get ‘test’,‘r1’, {FILTER => “ValueFilter(=, ’ binary:v2’)”}
获取test表中列值等于v2的所有信息
scan ‘test’, FILTER=>"ValueFilter(=,‘binary:v2’)"
查看test表中谁的列值包含88
scan ‘test’, FILTER=>"ValueFilter(=,‘substring:88’)"
ColumnPrefixFilter列修饰符前缀过滤器
查看test表中的列前缀为c2,列值包含88的用户
scan ‘test’, FILTER=>"ColumnPrefixFilter(‘c2’) AND ValueFilter(=,‘substring:88’)"
查看test表中的列前缀为s,列值包含123或者222的用户
scan ‘test’, FILTER=>"ColumnPrefixFilter(‘s’) AND ( ValueFilter(=,‘substring:123’) OR ValueFilter(=,‘substring:222’) )"
查看test表中,行键为user1开头的所有信息
scan ‘test’, FILTER => "PrefixFilter (‘user1’)"
查看test表中,从行键user开始,找到所有的rowkey以user1开头的信息
scan ‘test’, {STARTROW=>‘user’, FILTER => “PrefixFilter (‘user1’)”}
查看test表中,从行键user1开始找,找到所有的到行键uesr2之间的所有信息
scan ‘test’, {STARTROW=>‘user1’, STOPROW=>‘user2’}
修改表结构
必须先disable 关闭表
disable 'test’
alter ‘test’,{NAME=>‘userinfo’,age=>‘20’},{NAME=>‘callnum’, TTL=>‘15245667853’}
enable 'test’
表数据的增删改查
1.添加数据
给表a的添加一行记录:
语法:put < table>,< rowkey>,< family:column>,< value>,< timestamp>
put ‘a’,‘rowkey001’,‘f1:col1’,‘value01’ 时间戳系统默认
2.查询数据
查询表a,rowkey001中的f1下的col1的值
get ‘a’,‘rowkey001’, 'f1:col1’
3.查询表中的数据行数
语法:count < table>, {INTERVAL => intervalNum, CACHE => cacheNum}
INTERVAL设置多少行显示一次及对应的rowkey,默认1000;CACHE每次去取的缓存区大小,默认是10,调整该参数可提高查询速度
count ‘a’, {INTERVAL => 100, CACHE => 500}
解析:查询表a中的行数,每100条显示一次,缓存区为500
4.扫描表
语法:scan < table>, {COLUMNS => [ < family:column>,… ], LIMIT => num}
scan ‘a’,{LIMIT=>5}
解析:扫描表t1的前5条数据
5.删除数据
a.删除行中的某个列值
语法:delete < table>, < rowkey>, < family:column> , < timestamp> 必须指定列名
delete ‘a’,‘rowkey001’,'f1:col1’
解析:删除表a,rowkey001中的f1:col1的数据
b.删除行
语法:delete < table>, < rowkey>, < family:column> , < timestamp> 可以不指定列名,删除整行数据
delete all ‘a’,'rowkey001’
解析:删除表a,rowkey001中的所有数据
c.删除表中的所有数据
语法: truncate < table>
具体过程是:disable table -> drop table -> create table
truncate 'a’
解析:删除表a的所有数据
# 创建表,c1版本为4, 元数据mykey=myvalue
hbase(main):009:0> create 't1', {NAME => 'c1', VERSIONS => 4}, METADATA => { 'mykey' => 'myvalue' }
0 row(s) in 2.2810 seconds
=> Hbase::Table - t1
# 添加列族c2, c3
hbase(main):010:0> alter 't1', 'c2', 'c3'
Updating all regions with the new schema...
1/1 regions updated.
Done.
Updating all regions with the new schema...
1/1 regions updated.
Done.
0 row(s) in 3.8320 seconds
# 出入数据,c1 插入4个版本的值
hbase(main):011:0> put 't1', 'r1', 'c1', 'v1'
0 row(s) in 0.1000 seconds
hbase(main):012:0> put 't1', 'r1', 'c1', 'v11'
0 row(s) in 0.0180 seconds
hbase(main):013:0> put 't1', 'r1', 'c1', 'v111'
0 row(s) in 0.0140 seconds
hbase(main):014:0> put 't1', 'r1', 'c1', 'v1111'
0 row(s) in 0.0140 seconds
# 插入c2、c3的值
hbase(main):015:0> put 't1', 'r1', 'c2', 'v2'
0 row(s) in 0.0140 seconds
hbase(main):016:0> put 't1', 'r1', 'c3', 'v3'
0 row(s) in 0.0210 seconds
# 获取rowKey=r1的一行记录
hbase(main):017:0> get 't1', 'r1'
COLUMN CELL
c1: timestamp=1552819382575, value=v1111
c2: timestamp=1552819392398, value=v2
c3: timestamp=1552819398244, value=v3
3 row(s) in 0.0550 seconds
# 获取rowKey=r1并且 1552819392398 <= 时间戳范围 < 1552819398244
hbase(main):018:0> get 't1', 'r1', {TIMERANGE => [1552819392398, 1552819398244]}
COLUMN CELL
c2: timestamp=1552819392398, value=v2
1 row(s) in 0.0090 seconds
# 获取指定列的值
hbase(main):019:0> get 't1', 'r1', {COLUMN => 'c1'}
COLUMN CELL
c1: timestamp=1552819382575, value=v1111
1 row(s) in 0.0160 seconds
# 获取指定列的值,多个值使用数组表示
hbase(main):020:0> get 't1', 'r1', {COLUMN => ['c1', 'c2', 'c3']}
COLUMN CELL
c1: timestamp=1552819382575, value=v1111
c2: timestamp=1552819392398, value=v2
c3: timestamp=1552819398244, value=v3
3 row(s) in 0.0170 seconds
# 获取c1的值,获取4个版本的值,默认是按照时间戳降续排序的
hbase(main):021:0> get 't1', 'r1', {COLUMN => 'c1', VERSIONS => 4}
COLUMN CELL
c1: timestamp=1552819382575, value=v1111
c1: timestamp=1552819376343, value=v111
c1: timestamp=1552819368993, value=v11
c1: timestamp=1552819362975, value=v1
4 row(s) in 0.0180 seconds
# 获取c1的3个版本值
hbase(main):027:0* get 't1', 'r1', {COLUMN => 'c1', VERSIONS => 3}
COLUMN CELL
c1: timestamp=1552819382575, value=v1111
c1: timestamp=1552819376343, value=v111
c1: timestamp=1552819368993, value=v11
3 row(s) in 0.0090 seconds
# 获取指定时间戳版本的列
hbase(main):022:0> get 't1', 'r1', {COLUMN => 'c1', TIMESTAMP => 1552819376343}
COLUMN CELL
c1: timestamp=1552819376343, value=v111
1 row(s) in 0.0170 seconds
hbase(main):023:0> get 't1', 'r1', {COLUMN => 'c1', TIMESTAMP => 1552819376343, VERSIONS => 4}
COLUMN CELL
c1: timestamp=1552819376343, value=v111
1 row(s) in 0.0130 seconds
# 获取rowKey=r1中的值等于v2的所有列
hbase(main):024:0> get 't1', 'r1', {FILTER => "ValueFilter(=, 'binary:v2')"}
COLUMN CELL
c2: timestamp=1552819392398, value=v2
1 row(s) in 0.0510 seconds
hbase(main):025:0> get 't1', 'r1', {COLUMN => 'c1', ATTRIBUTES => {'mykey'=>'myvalue'}}
COLUMN CELL
c1: timestamp=1552819382575, value=v1111
1 row(s) in 0.0100 seconds
namespace命令
-
列举命名空间
list_namespace -
获取命名空间描述
describe_namespace -
查看命名空间下的所有表
list_namespace_tables -
创建命名空间
create_namespace 'test’ -
修改命名空间的属性
alter_namespace ‘test’, {METHOD => ‘unset’, NAME=>‘PROPERTY_NAME’} -
删除命名空间
drop_namespace
权限管理
1)分配权限
权限用五个字母表示: “RWXCA”
READ(‘R’), WRITE(‘W’), EXEC(‘X’), CREATE(‘C’), ADMIN(‘A’)
grant ‘test’,‘RW’,'a’
解析:给用户‘test’分配对表a有读写的权限
2)查看权限
user_permission 'a’
解析:查看表a的权限列表
3)收回权限
revoke ‘test’,'a’
解析:收回test用户在表a上的权限
查询表中有多少行 count
count '表名’
自增 incr
incr ‘表名’, ‘行键’, ‘列族:列名’, 步长值
注意:incr 可以对不存的行键操作,如果行键已经存在会报错,如果使用put修改了incr的值再使用incr也会报错
ERROR: org.apache.hadoop.hbase.DoNotRetryIOException: Field is not a long, it’s 2 bytes wide
计数器 get_counter
# 点击量:日、周、月
create 'counters', 'daily', 'weekly', 'monthly'
incr 'counters', '20110101', 'daily:hits', 1
incr 'counters', '20110101', 'daily:hits', 1
get_counter 'counters', '20110101', 'daily:hits'
修饰词
1.COLUMNS: 查询同一个列族的多个列
语法:
scan ‘表名’, {COLUMNS => [ ‘列族名1:列名1’, ‘列族名1:列名2’, …]}
示例:scan ‘tbl_user’, {COLUMNS => [ ‘info:id’, ‘info:age’]}
2 TIMESTAMP 指定时间戳
语法:
scan ‘test’, {COLUMNS => ‘a1’, TIMESTAMP=> 1552818347657}
3 TIMERANGE 表示的是”>=开始时间 and <结束时间“
语法:
scan ‘表名’,{TIMERANGE=>[timestamp1, timestamp2]}
4 VERSIONS 版本
默认情况下一个列只能存储一个数据,后面如果修改数据就会将原来的覆盖掉,可以通过指定VERSIONS时HBase一列能存储多个值。
create 'test', 'columnFamily'
describe 'test'
# 修改列族版本号
alter 'test', { NAME=>'columnFamily', VERSIONS=>3 }
put 'test', 'rowKey1', 'columnFamily:column1', 'value1'
put 'test', 'rowKey1', 'columnFamily:column1', 'value2'
put 'test', 'rowKey1', 'columnFamily:column1', 'value3'
# 默认返回最新的一条数据
get 'test','rowKey1','columnFamily:column1'
# 返回3个
get 'test','rowKey1',{COLUMN=>'columnFamily:column1', VERSIONS=>3}
# 返回2个
get 'test','rowKey1',{COLUMN=>'columnFamily:column1', VERSIONS=>2}
5 STARTROW 行键起始行
ROWKEY起始行。会先根据这个key定位到region,再向后扫描
语法:
scan ‘表名’, { STARTROW => ‘行键名’}
6 STOPROW :截止到STOPROW行,STOPROW行之前的数据,不包括STOPROW这行数据
语法:
scan ‘表名’, { STOPROW => ‘行键名’}
7 LIMIT 返回的行数
语法:
scan ‘表名’, { LIMIT => 行数}
HBase 常见错误
hbase shell在使用的时候经常会报错,这里列举了几个错误:
1.ERROR: org.apache.hadoop.hbase.ipc.ServerNotRunningYetException: Server is not running yet
使用jps查看是否有datanode服务
jps
删除hadoop 的临时目录
/opt/soft/hadoop260/tmp
2.ERROR: Can’t get master address from ZooKeeper; znode data == null
关闭hbase
stop-hbase.sh
重启hbase
start-hbase.sh
通过多次重启hbase服务或者是格式化namenode和DataNode,解决问题。
3.ERROR: org.apache.hadoop.hbase.PleaseHoldException: Master is initializing
解决办法1:
第一个问题,端口问题8020
hadoop默认的namenode 资源子接口是8020 端口,端口改成9000.
第二个问题,命名
修改配置文件hbase-site.xml
改成如图所示:hbase.root.dir