HBase学习笔记-入门(4)-HBase的Shell操作

HBase Shell

HBase数据库默认的客户端程序是HBase Shell,这是一个命令行工具,类似于MySQL客户端启动后出现的命令行Shell。在启动HBase集群之后(同时配置了环境变量),在命令行中输入hbase shell即可进入。

HBase Shell是一个封装了Java客户端API的JRuby应用软件,其中提供的命令可以理解成为是Ruby函数的调用,每个命令都是一个Ruby脚本,后面跟着的参数为传入的参数,具体格式在后续进行说明。在下面链接中列出了在HBase Shell中可用的所有脚本:

hbase/hbase-shell/src/main/ruby/shell/commands at master · apache/hbase (github.com)

在 Shell 中输入help可以获取可用命令列表,输入help commandname可获取特定命令的帮助,还可以输入各种命令查看集群、数据库和数据的各项详情。

  • 使用status命令查看当前集群各节点的状态
  • 使用version命令查看当前 HBase 的版本号
  • 使用命令exitquit即可退出 HBase Shell
  • 使用whoami命令显示当前用户

HBase Shell提供的命令可以大致分为两类,一类是对数据表的管理命令,包括对表的创建,禁用,删除等操作;另一类是对表中数据的增删改查命令。

数据表管理命令

常用命令汇总:

命令 描述
create 创建指定模式的新表
alter 修改表的结构,如添加新的列族等
describe 展示表结构信息,包括列族的数量与属性等
list 列出HBase中已有的表
exists 判断某个表是否存在
disable / enable 禁用 / 解禁一个表。在删除和更改表之前,需要禁用这个表
disable_all 禁用所有的表,可以使用正则表达式匹配
is_disable 判断一个表是否被禁用
drop 删除表
truncate 删除表中数据。truncate可以禁用表、删除表并自动重建表结构

命令使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 创建表: 使用create命令,需要指明表名,列族名
create "MY_TABLE", "C1", "C2"

# 修改表: 使用alter命令,指定表名以及需要做什么样的修改
# 改变列族C1的版本保存数目
alter "MY_TABLE", {NAME => "C1", VERSION => 6}

# 增加列族C3
alter "MY_TABLE", "C3"

# 删除列族C3,下面两种方式都可以(HBase表中至少要包含一个列族,当表中只有一个列族的时候,无法将其删除)
alter "MY_TABLE", "delete" => "C3"
alter "MY_TABLE", {NAME => "C3", METHOD => "delete"}

# 删除表: 首先需要禁用表,然后才能删除
disable "MY_TABLE"
drop "MY_TABLE"

# 清空表中的数据,相当于禁用表,删除表,按照原结构重建表
truncate "MY_TABLE"

前面提到HBase Shell命令都是Ruby脚本,可以理解为对Ruby函数的调用,不同的函数传入参数的形式不同。传入引号包裹的字符串就是传入字符串;传入{}包裹的参数,表示传入一个类似Map的结构,其中Map的每一个键值对有key => value的格式,key一般是给定的参数,不使用引号标识;传入[]包裹的参数,表示传入一个类似数组的结构

增删改查命令

常用命令汇总:

命令 描述
put 添加一个值到指定单元格中
get 通过表名、行键等参数获取行或者单元格的数据
scan 遍历表并输出满足指定条件的行记录
count 计算表中的逻辑行数(会遍历所有的存储数据,谨慎使用)
delete 删除表中列族或者列的数据
deleteall 删除逻辑行

命令使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 添加数据: 使用put命令,但是每次只能保存一个列的值
# put命令需要指定表名, 行键, 列族名:列标识符, 值, [时间戳]
# 时间戳是可选项,如果没有显式指定,则系统自动插入当前时间戳
put "MY_TABLE", "000001", "C1:Name", "test"

# 更新数据,同样使用put命令

# 查看数据: 使用get命令,可以获取行或者单元格的数据
# 表名,行键获取一行的数据
# 表名,行键,列族名:列标识符 获取单元格的数据
# 中文的显示 {FORMATTER => 'toString'}
get "MY_TABLE", "000001"
get "MY_TABLE", "000001", "C1:Name", {FORMATTER => 'toString'}

# 查看全表,使用scan命令
scan "MY_TABLE"

# 限制查询数目
scan "MY_TABLE", {LIMIT => 3, FORMATTER => 'toString'}

# 指定查询的列
scan "MYTABLE", {COLUMNS => ['C1:Name','C2:Address']}

# 指定查询的行键
scan "MY_TABLE", {ROWPREFIXFILTER => '000001'}

# 删除数据
# 删除某一个单元格的数据,使用delete
delete "MY_TABLE", "000001", "C1:Name"
# delete无法跨列族操作,如果要删除一个逻辑行,需要使用deleteall命令
deleteall "MY_TABLE", "000001"

需要注意的是,delete操作并不会马上删除数据,只会将对应的数据打上删除标记,在空闲合并数据的时候,数据才会被删除。同时delete删除的是最新版本的数据。

HBase过滤器

在HBase中,get和scan操作可以使用过滤器来设置输出的范围,增加查询的条件,类似于SQL里面的where条件。在HBase Shell中使用show_filter命令可以查看当前HBase支持的过滤器类型。过滤器的实现使用的是Java,HBase Shell命令相当于封装了一层进行API的调用。

过滤器的语法格式如下:

1
scan "表名", {FILTER => "过滤器(比较运算符, '比较器表达式')"}
  • 过滤器表示过滤的层次,如行键过滤器、列族过滤器等
  • 比较运算符即表示判断逻辑,如等于,大于,小于等
  • 比较器表达式表示进行比较的值,如匹配完整字节数组,匹配子字符串等

过滤器可以在官方API中找到 org.apache.hadoop.hbase.filter (Apache HBase 3.0.0-alpha-3-SNAPSHOT API) 。所在包为package org.apache.hadoop.hbase.filter

比较运算符:=><>=<=!=

比较器:

比较器 表达式语言缩写 描述
BinaryComparator binary:value 匹配完整字节数组
BinaryPrefixComparator binaryprefix:value 匹配字节数组前缀
BitComparator bit:value 匹配比特位
NullComparator null 匹配空值
RegexStringComparator regexstring:正则表达式 匹配正则表达式
SubstringComparator substring:value 匹配子字符串

并且如果需要使用多个过滤器共同来实现查询,可以使用AND或者OR来组合多个过滤器来完成查询

但是需要注意的是,在HBase Shell中默认都是字符串比较,如果比较数值类型,可能会出现不准确的情况。

下面介绍一些常用的过滤器以及对应的使用方法。

行键过滤器

行键过滤器,RowFilter,可以实现对行键字符串的比较和过滤。

1
2
3
4
5
# 如果行键是1234的子字符串,则匹配
scan "MY_TABLE", {FILTER => "RowFilter(=, 'substring:1234')"}

# 如果行键大于hahaha(字符串顺序),则匹配
scan "MY_TABLE", {FILTER => "RowFilter(>, 'binary:hahaha')"}

其他行键过滤器描述:

行键过滤器 描述
PrefixFilter 行键前缀比较器
KeyOnlyFilter 只显示单元格的键(列族名:列标识符),不显示值
FirstKeyOnlyFilter 对于每一行,只显示第一个单元格
InclusiveStopFilter 指定终止条件行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# PrefixFilter
# 下面两种方式等价, PrefixFilter无需结合运算符和比较器
scan "MY_TABLE", {FILTER => "PrefixFilter('0001')"}
scan "MY_TABLE", {FILTER => "RowFilter(=, 'binaryprefix:0001')"}

# KeyOnlyFilter
scan "MY_TABLE", {FILTER => "KeyOnlyFilter()"}

# FirstKeyOnlyFilter
scan "MY_TABLE", {FILTER => "FirstKeyOnlyFilter()"}

# InclusiveStopFilter
# 下面两种方式等价
scan "MY_TABLE", {STARTROW => '0001', FILTER => "InclusiveStopFilter('binary:0002')"}
scan "MY_TABLE", {STARTROW => '0001', ENDROW => '0003'}

列族与列过滤器

列族过滤器,FamilyFilter,根据列族字符串进行比较和过滤

1
2
# 匹配所有列族为C1的单元格
scan "MY_TABLE", {FILTER => "FamilyFilter(=, 'binary:C1')"}

其他列过滤器描述:

列过滤器 描述
QualifierFilter 列标识符过滤器,根据列标识符进行过滤
ColumnPrefixFilter 对列标识符前缀进行过滤
MultipleColumnPrefixFilter 可以指定多个前缀对列标识符进行过滤
ColumnRangeFilter 过滤列标识符名称的范围,指定区间,同时可以指定区间开闭
1
2
3
4
5
6
7
8
9
10
11
12
13
# QualifierFilter
scan "MY_TABLE", {FILTER => "QualifierFilter(=, 'binary:Math')"}

# ColumnPrefixFilter
# ColumnPrefixFilter无需结合运算符和比较器
scan "MY_TABLE", {FILTER => "ColumnPrefixFilter('Ma')"}

# MultipleColumnPrefixFilter
scan "MY_TABLE", {FILTER => "MultipleColumnPrefixFilter('Ma', 'Ag')"}

# ColumnRangeFilter
# 下面命令指定为左开右闭
scan "MY_TABLE", {FILTER => "ColumnRangeFilter('Big', ture, 'Math', false)"}

值过滤器

值过滤器按照单元格的值进行匹配和过滤。

值过滤器 描述
ValueFilter 值过滤器,根据单元格中的值找到符合条件的键值对
SingleColumnValueFilter 指定对应列族和列,按照定位到的值进行比较
SingleColumnValueExcludeFilter 排除匹配成功的值,与上一个过滤器的扫描结果相反
1
2
3
4
5
6
7
8
9
10
# ValueFilter,匹配所有值为haha的单元格
scan "MY_TABLE", {FILTER => "ValueFilter(=, 'binary:haha')"}

# SingleColumnValueFilter,指定列族,列标识符,比较运算符,比较器
# 匹配所有C1:Name项值为haha的单元格
scan "MY_TABLE", {FILTER => "SingleColumnValueFilter('C1', 'Name', =, 'binary:haha')"}

# SingleColumnValueExcludeFilter
# SingleColumnValueFilter的反向匹配
scan "MY_TABLE", {FILTER => "SingleColumnValueExcludeFilter('C1', 'Name', =, 'binary:haha')"}

其他过滤器

过滤器 描述
ColumnCountGetFilter 限制每个逻辑行中返回键值对的个数
TimestampsFilter 根据时间戳进行过滤,可以同时设置多个时间戳
InclusiveStopFilter 设置停止行,扫描到对应行就停止扫描
PageFilter 对显示结果按行进行分页显示
ColumnPaginationFilter 对一个逻辑行内的所有列进行分页,返回[offset, offset+limit]范围内的列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# ColumnCountGetFilter 
get "MY_TABLE", {FILTER => "ColumnCountGetFilter(3)"}

# TimestampsFilter
scan "MY_TABLE", {FILTER => "TimestampsFilter(1, 3)"}

# InclusiveStopFilter
scan "MY_TABLE", {STARTROW => '0001', ENDROW => '0005', FILTER => "InclusiveStopFilter('0003')"}

# PageFilter
scan "MY_TABLE", {STARTROW => '0001', ENDROW => '0005', FILTER => "PageFilter(3)"}

# ColumnPaginationFilter
scan "MY_TABLE", {STARTROW => '0001', ENDROW => '0005', FILTER => "ColumnPaginationFilter(2, 1)"}

其他操作

数据上传与导出

我们可以通过一个txt文件来完成数据的上传,在这个txt文件中每一行都是一条能够在HBase Shell中执行的命令。我们可以在HBase Shell之外,在Linux命令行中执行下面的命令,将txt文件中的命令一次全部执行。这一过程类似于MySQL中对.sql文件的source操作

1
hbase shell [txt文件在Linux文件系统中的位置]

还可以使用提供的MapReduce程序进行数据上传,在HBase中提供了一个用于Import的MapReduce作业,专门用来将数据文件导入到HBase中,用法如下:

1
hbase org.apache.hadoop.hbase.mapreduce.Import 表名 HDFS数据文件路径

对应还存在一个数据导出的MapReduce程序:

1
hbase org.apache.hadoop.hbase.mapreduce.Export 表名 HDFS输出路径

大量数据的计数统计

当HBase中数据量大的时候,可以使用HBase中提供的MapReduce程序来进行计数统计,语法如下:

1
$HBASE_HOME/bin/hbase org.apache.hadoop.hbase.mapreduce.RowCounter "表名"

incr

incr可以实现对某个单元格的值进行原子性计数,语法如下:

1
incr "表名", "rowkey", "列族:列标识符", [累加值,默认为1]

如果某一列需要实现计数功能,必须使用incr来创建对应的列,使用put创建的列是不能实现累加功能的。

对于incr创建的列,需要使用get_counter来访问,格式与get命令类似。

参考文章

  1. HBase过滤器入门教程

HBase学习笔记-入门(4)-HBase的Shell操作
http://example.com/2022/04/17/HBase学习笔记-入门-4-HBase的Shell操作/
作者
EverNorif
发布于
2022年4月17日
许可协议