HBase表管理

HBase的表管理对应于前面提到的DDL命令,它定义了对表及其结构的操作,包括表的创建、结构修改、表的停用、表的删除、批量停用与删除表等。

主要内容包括:

HBase将行存储在表中,每个表被划分为“region”。这些region分布在集群中,由系统中的RegionServer进程托管并提供给客户端进程使用。表中的所有行在region开始键和结束键之间排序。每一行都恰好属于一个region,而一个region在任何给定的时间点都由单个region server提供服务

从Shell创建HBase表

使用create命令能够创建一张HBase表,需要指定的参数包括命名空间、表名称、列族名称。

创建HBase表的语法如下所示:

CREATE 'name_space:table_name', 'column_family'

注意,表名的命名空间是可选的,如果没有指定,它会在默认命名空间(default)中创建一个表。而column_family是强制性的,至少需要一个列族才能成功创建表。如果未指定,则返回一个错误。

下面的示例在default命名空间中创建一个“emp”表,并将列族设置为“office”。

hbase> CREATE 'emp', 'office'

当试图使用已经存在的名称创建一个表时,无论列族是否相同,都将得到错误消息。一个命名空间中的HBase表应该是唯一的。

HBase分割表

HBase表被分割并将数据存储到几个region中。表创建时,HBase默认只分配一个region给它。让我们看看如何将表划分为多个区域并有效地使用集群的示例。

HBase分割表语法如下所示:

CREATE 'name_space:table_name', 'column_family'  SPLITS => ['10', '20', '30', '40']

下面的示例代码创建了一个新的表dep:

hbase> CREATE 'dep', 'office', SPLITS => ['10', '20', '30']

当创建表时,还可以指定许多选项,请参考HBase Shell命令速查-DDL命令

列表显示HBase表

使用list命令显示HBase中所有的用户表。列表还支持可选的正则表达式来过滤输出。列表的语法如下所示。

 list '<namespace>:<regular expression>'

要显示所有表,只需使用不带任何参数的list命令。当表属于一个名称空间时,结果上将显示名称空间。

使用list命令可列出所有的表:

hbase> list

另外,还可以使用表名和限定名称空间。当没有找到表时,它返回0行。

使用正则表达式过滤列表结果

如果您想过滤结果,可以使用正则表达式,如下所示:

hbase> list '.*mp.*'

描述表信息

可以使用describe命令描述HBase表的详细信息和配置。例如,版本、压缩、块大小、复制等等。描述表的语法如下。

describe <'namespace':'table_name'>

例如,查看表emp的详细信息和配置:

hbase> describe 'emp'

在命名空间中创建表时,需要通过命令对其进行限定。在上面的示例中,我们没有限定名称空间。

describe命令还将返回表的启用或禁用状态。

使用put命令向HBase表插入数据

使用PUT命令向HBase表的行和列插入数据。这类似于RDBMS上的插入语句,但是语法完全不同。

下面是PUT命令的语法,用于向HBase表中插入数据(行和列)。

put '<name_space:table_name>', '<row_key>' '<cf:column_name>', '<value>'

下面是一些向HBase表emp插入数据的示例。

hbase> put 'emp', '1' , 'office:name', 'Scott'
hbase> put 'emp', '2' , 'office:name', 'Mark'
hbase> put 'emp', '2' , 'office:gender', 'M'
hbase> put 'emp', '2' , 'office:age', '30'
hbase> put 'emp', '2' , 'office:age', '50'

在上面的例子中,注意我们添加了2行;行键“1”有一列“office:name”,行键“2”有三列“office:name”,“office:gender”和“office:age”。

另外,请注意,上面示例中的最后一个命令实际上在行键“2”上用“50”插入了一个新列“office:age”。在内部,HBase不做更新,但它分配一个带有新的时间戳的列,并且扫描时从列中获取最新的数据。

下面添加插入更多的行:

hbase> put 'emp', '3', 'office:salary', '10000'
hbase> put 'emp', '3', 'office:name', 'Jeff'
hbase> put 'emp', '3', 'office:salary', '20000'
hbase> put 'emp', '3', 'office:salary', '30000'
hbase> put 'emp', '3', 'office:salary', '40000'
hbase> put 'emp','1','office:age','20'
hbase> put 'emp','3','office:age','30'

通过HBase Shell验证表是否存在

使用exists命令验证数据库中是否存在指定的表。其语法如下:

exists '<namespace>:<table_name>'

例如,判断HBase数据库中是否存在emp表:

hbase> exists 'emp'
hbase> exists 'emp123'

执行exists将与消息一起返回布尔值。当表存在于数据库中时返回'true',当表在数据库中不存在时返回' false '。。

通过HBase Shell统计表记录数量

使用count命令获取表中的总记录。其语法如下:

count '<namespace>:<table_name>'

例如,统计表emp中记录数:

hbase> count 'emp'

执行这个命令,会返回表中的行数。

当表不存在时,该方法会返回"Unknown table"。

使用HBase Shell从HBase表中读取(扫描)Rows

使用scan命令从HBase表中获取数据。默认情况下,它从表中获取所有数据。例如:

hbase> scan 'emp'

我们可以通过传入扫描器规范limit来限制结果。下面的示例限制为一行。

hbase> scan 'emp', {LIMIT => 1}

下面的命令限制查询的结果为2行"1"和"2":

hbase> scan 'emp', {LIMIT => 2}

使用COLUMN规范,我们可以列出具有指定有列的行。例如:

hbase> scan 'emp', {LIMIT => 2, COLUMN => ['office:name']}

下面的命令返回具有'name'和'age'列的两行记录:

hbase> scan 'emp', {LIMIT => 2, COLUMNS => ['office:name','office:age']}

我们还可以指定STARTROW,结果从这里返回:

hbase> scan 'emp', {LIMIT => 2, COLUMNS => ['office:name','office:age'], STARTROW => '2'}

也可以指定STOPROW规范,指定到哪里停止:

hbase> scan 'emp', {COLUMNS => ['office:name','office:age'], STARTROW => '1', STOPROW => '3'}

要列出所有已删除的列,需要使用RAW选项:

hbase> scan 'emp', {RAW => true}

下面是更多的scan命令使用示例:

hbase> scan 'hbase:meta'
hbase> scan 'hbase:meta', {COLUMNS => 'info:regioninfo'}
hbase> scan 'ns1:t1', {COLUMNS => ['c1','c2'], LIMIT => 10, STARTROW => 'xyz'}
hbase> scan 't1', {COLUMNS => ['c1','c2'], LIMIT => 10, STARTROW => 'xyz'}
hbase> scan 't1', {COLUMNS => 'c1', TIMERANGE => [1303668804000, 1303668904000]}
hbase> scan 't1', {REVERSED => true}
hbase> scan 't1', {ALL_METRICS => true}
hbase> scan 't1', {METRICS => ['RPC_RETRIES','ROWS_FILTERED']}
hbase> scan 't1', {ROWPREFIXFILTER => 'row2', FILTER => "(QualifierFilter(>=, 'binary:xyz')) AND (TimestampsFilter(123,456))"}
hbase> scan 't1', {FILTER => org.apache.hadoop.hbase.filter.ColumnPaginationFilter.new(1,0)}
hbase> scan 't1', {CONSISTENCY => 'TIMELINE'}
hbase> scan 't1', {ISOLATION_LEVEL => 'READ_UNCOMMITTED'}
hbase> scan 't1', {MAX_RESULT_SIZE => 123456}
# 设置运算属性
hbase> scan 't1', {COLUMNS => ['c1','c2'], ATTRIBUTES => {'mykey' => 'myvalue'}}
hbase> scan 't1', {COLUMNS => ['c1','c2'], AUTHORIZATIONS => ['PRIVATE', 'SECRET']}
# 对于专家来说,还有一个额外的选项--CACHE_BLOCKS--用于scanner的块缓存切换开关,默认是enabled
hbase> scan 't1', {COLUMNS => ['c1','c2'], CACHE_BLOCKS => false}

使用Scan读取数据时指定过滤器

在使用HBase Scan时,我们可以在列上使用类似于SQL中的WHERE子句的谓词条件来过滤表中的行/记录。为了使用过滤器,需要在HBase Shell中导入一些Java类。

SingleColumnValueFilter

为了使用Scan在HBase shell上过滤行,需要导入org.apache.hadoop.hbase.filter.SingleColumnValueFilter类以及下面解释的一些其他类。

hbase> import org.apache.hadoop.hbase.filter.SingleColumnValueFilter
hbase> import org.apache.hadoop.hbase.filter.CompareFilter
hbase> import org.apache.hadoop.hbase.filter.BinaryComparator

示例1:返回name=='Jeff'的行:

hbase> scan 'emp', { FILTER => SingleColumnValueFilter.new(Bytes.toBytes('office'), Bytes.toBytes('name'), CompareFilter::CompareOp.valueOf('EQUAL'),BinaryComparator.new(Bytes.toBytes('Jeff')))}

执行以上命令,返回内容如下:

ROW                         COLUMN+CELL
3                          column=office:age, timestamp=1567542149583, value=30
3                          column=office:name, timestamp=1567542103821, value=Jeff
3                          column=office:salary, timestamp=1567542130044, value=40000
1 row(s)
Took 0.0480 seconds

示例2:返回年龄不小于50的行:

hbase> scan 'emp', { FILTER => SingleColumnValueFilter.new(Bytes.toBytes('office'), Bytes.toBytes('age'), CompareFilter::CompareOp.valueOf('GREATER_OR_EQUAL'),BinaryComparator.new(Bytes.toBytes('50')))}

执行以上命令,返回内容如下:

ROW                         COLUMN+CELL
2                          column=office:age, timestamp=1567541901009, value=50
2                          column=office:gender, timestamp=1567541880523, value=M
2                          column=office:name, timestamp=1567541868638, value=Mark
1 row(s)
Took 0.0180 seconds

示例3:返回列值等于40000的行:

hbase> scan 'emp', {FILTER => "ValueFilter (=,'binaryprefix:40000')"}

执行以上命令,返回内容如下:

ROW                         COLUMN+CELL
3                          column=office:salary, timestamp=1567542130044, value=40000
1 row(s)
Took 0.0034 seconds

用HBase shell从表中获取单个行和特定列

使用get从单行及其列中检索数据。命令get的语法如下所示。

get '<namespace>:<table_name>', '<row_key>', '<column_key>'

示例:下面的命令返回行键为'2'的行及其所有列:

hbase> get 'emp','2'

示例:下面的命令返回行键为'2'的行及其'office:age'列和'office:name'列。

hbase> get 'emp','2', 'office:age', 'office:name'

或者,使用下面的命令,返回相同的结果:

hbase> get 'emp','2', {COLUMNS => ['office:age', 'office:name']}

更多get命令使用示例如下:

hbase> get 'ns1:t1','r1'
hbase> get 't1','r1',{TIMERANGE => [ts1, ts2]}
hbase> get 't1','r1',{COLUMN => 'c1'}
hbase> get 't1','r1',{COLUMN => ['c1','c2','c3']}
hbase> get 't1','r1',{COLUMN => 'c1', TIMESTAMP => ts1}
hbase> get 't1','r1',{COLUMN => 'c1', TIMERANGE => [ts1, ts2], VERSIONS => 4}
hbase> get 't1','r1',{COLUMN => 'c1', TIMESTAMP => ts1, VERSIONS => 4}
hbase> get 't1','r1',{FILTER => "ValueFilter(=, 'binary:abc')"}
hbase> get 't1','r1', 'c1'
hbase> get 't1','r1', 'c1', 'c2'
hbase> get 't1','r1', ['c1', 'c2']
hbase> get 't1','r1',{COLUMN => 'c1', ATTRIBUTES => {'mykey' => 'myvalue'}}
hbase> get 't1','r1',{COLUMN => 'c1', AUTHORIZATIONS => ['PRIVATE','SECRET']}
hbase> get 't1','r1',{CONSISTENCY => 'TIMELINE'}
hbase> get 't1','r1',{CONSISTENCY => 'TIMELINE', REGION_REPLICA_ID => 1}

使用HBase Shell禁用和启用表

我们可以使用HBase shell禁用和启用现有的HBase表。

禁用表

使用'disable'禁用一个表。在删除表或更改其设置之前,首先需要禁用该表。禁用表的语法如下所示。

disable '<namespace>:<table_name>'

例如,要禁用表'emp':

hbase> disable 'emp'

使用is_disabled检查表是否被禁用。当表被禁用时它会返回"true":

hbase> is_disabled 'emp'

还要以使用describe来查看表的描述信息,在描述信息中包含了该表是否被禁用的信息。

hbase> describe 'emp'

一旦该表被禁用,就不能执行常规的操作命令。

启用表

使用'enalbe'来启用一个被禁用的表。需要首先启用一个被禁用的表来执行任何常规命令。启用表的语法如下。

hbase> enable '<namespace>:<table_name>'

例如,要启用之前被禁用的'emp'表:

hbase> enable 'emp'

使用describe命令查看该表是否被启用:

hbase> describe 'emp'

删除HBase表中的行

我们可以使用delete和deleteall命令从HBase表中删除整行和一行的特定列单元格。

使用deleteall命令

使用deleteall命令从HBase表中删除指定的行。它将表名和行作为强制参数,列和时间戳作为可选参数。它还支持使用行键前缀删除行范围。deleteall的语法如下所示。

deleteall '<table_name>', 'row_key', '<column_name>'

例如,要从表'emp'中删除行'1'及其所有单元格。

hbase> deleteall 'emp', '1'

示例:从row '2'中删除所有单元'office:age'

hbase> deleteall 'emp', '2', 'office:age'

运行scan命令扫描表不会获取删除的行和列。

使用CACHE选项,指定一次要发送多少批数据到服务器,这主要用于处理较大的数据集。当未指定时,默认为100。

hbase> deleteall 'emp', {CACHE => 100}

更多deleteall的示例如下所示:

hbase> deleteall 't1','r1','c1', ts1
hbase> deleteall 't1','r1','c1', ts1, {VISIBILITY => 'PRIVATE|SECRET'}
hbase> deleteall 't1',{ROWPREFIXFILTER => 'prefix'}
hbase> deleteall 't1',{ROWPREFIXFILTER => 'prefix'}, 'c1'
hbase> deleteall 't1',{ROWPREFIXFILTER => 'prefix'}, 'c1', ts1
hbase> deleteall 't1',{ROWPREFIXFILTER => 'prefix'}, 'c1', ts1, {VISIBILITY => 'PRIVATE|SECRET'}
hbase> deleteall 't1',{ROWPREFIXFILTER => 'prefix', CACHE => 100}

使用delete命令

使用delete命令从表中删除一行中的一列。与deleteall不同,delete命令将'column cell'作为表和行键的强制参数。可以选择使用时间戳。

delete的语法如下。

delete '<table_name>', 'row_key', '<column_name>'

例如:从't1'表的'r1'行删除时间戳为'ts1'的'c1'单元格:

hbase> delete 't1', 'r1', 'c1', ts1

示例:

hbase> delete 't1', 'r1', 'c1', ts1, {VISIBILITY=>'PRIVATE|SECRET'}

《Spark原理深入与编程实战》