Hbase之数据模型与操作
0 前言
Hbase是apache社区维护的KV、列式存储
的NoSQL数据库,类似于goolgle的Bigtable,可以依附于不同的文件系统,如HDFS,S5,就如bigtable一样依附于GFS文件系统一样。
1 Data Model(数据模型)
1.1 NameSpace
namespace就类似于传统数据库中的database,主要是用来对不同的表进行分类与管理,Hbase默认已经定义好的namespace有2个:default、hbase。
常用的namespace的操作如下。
# 创建一个namespace : my_ns
create_namespace 'my_ns'
# 在my_ns命名空间中创建一个表,hbase中的column family由于动态创建代价太大,一般都是预定义,其中my_table是表名,其中fam是该表中的预先定义的column family
create 'my_ns:my_table', 'fam'
# 删除一个命名空间
drop_namespace 'my_ns'
# 修改一个命名空间的属性
alter_namespace 'my_ns', {METHOD => 'set', 'PROPERTY_NAME' => 'PROPERTY_VALUE'}
1.2 Table
table在Hbase中的概念就如传统数据库中的table,只是该table支持稀疏存储,支持动态的数据类型,可以存储任何数据,可以存储海量数据,常用的Table DDL操作如下。
create 'mytable','cf1'
#删除一个table的时候,必须先禁用该表的操作
disatble 'mytable'
drop 'mytable'
# 此外我们还可给table进行alter添加或者修改默认配置项
1.3 Row
在Hbase中,逻辑上是按照不同的row进行组织的,每个rowkey对应一条数据,同时rowkey是按照字典顺序进行排序的,所以rowkey的设计非常重要
,rowkey在物理存储的层面是按照字节数组进行存储的,空的字节数组代表命名空间的开始和结束。
1.4 Column
因为在hbase中,物理上所有的数据都是按照列式存储的,所以在hbase中是有列的概念,实际上column是由多个 column family下的多个column qualifier组成的。
1.5 Column Family
Hbase的Table实际上是由Row和Column Family组成,其中Column Family的中文释义是列簇,不同的列簇一般存放不同的数据,列簇可以由不同的Column Qualifier组成,在Hbase中简单的一行案例如下。
- Column Family一般是在创建table的时候预先定义好的,修改列簇。
create 'tableA','f1','f2'
#往tableA的f1列簇下添加name属性以及值,Hbase更像一个KV存储
put 'tableA','f1:name','hello'
1.6 Column Qualifier
Hbase的Column Family是固定的,但是一个Column Family下面理论上可以有不设限的Column Qualifier的数量,Column Family与Column Qualifier之间使用:
进行分割。
columnfamily1:name #其中name就是一个属性的修饰
1.7 Cell
因为Hbase是列式存储,每个Row与Column的交接点就是一个Cell或者多个cell,一般通过一个{row,column,version}
确定一个Cell,每个Cell实际上是不设限的字节,这也就保证了hbase可以存储所有类型的数据。
1.8 version
Hbase通过一个{row,column,version}
确定一个Cell,所以在row与column的交界处可能会有无数个cells,rowkey和columnfamily:columnqualifier描述都相同,但是只有version这个维度是不同的,Hbase的所有数据都按照byte数组进行存储,除了version,它按照long类型存储,通常是当前日期的时间戳,你可以在插入数据的时候手动指定该long类型的version值。
- 如果对相同的数据有着相同的version,那么最后一次写入的version是可获取的数据。
- 写入数据的时候可以不按照升序的方式进行写入。
1.8.1 如何指定存储的最大version数量
hbase存储的最大的版本数量是列模式的一部分,version可以在创建表的时候创建 ,也可以通过alter命令行的方式修改HColumnDescriptor.DEFAULT_VERSIONS
.
- 在Hbase0.96之前,保留的默认的最大版本数为3
- 在Hbase0.96及以后,保留的默认的最大版本数为1
简单的示例如下,通过hbase shell保留f1列簇中的所有列的最多5个版本。
hbase> alter't1',NAME =>'f1',VERSIONS => 5
我们还可以通过Hbase的JavaAPI使用HColumnDescriptor来进行版本的指定与修改。
在Hbase0.98.2开始,我们可以通过hbase.column.max.version
在hbase-site.xml中指定该参数的默认值。
1.8.2 如何指定存储的最小version数量
hbase> alter't1',NAME =>'f1',MIN_VERSIONS => 2
2 Data Model Operations
2.1 get
get操作是在Table的基础上进行操作的,可以按照1个或者多个rowkey的信息fetch到对应的数据,get是以rowkey为粒度的,通过Table.get
进行操作。
table = conn.getTable()
table.get(new Get())
table.get(List<Get> gets)
2.2 put
put操作是往Hbase的table中写入数据,也是以rowkey为粒度。
table = conn.getTable()
table.put(new Put().add...)
2.3 scan
scan操作允许扫描table获取多个Rows的数据,可以对rowkey作限定,比如说一下案例,只扫描以“row”开头的行的数据
public static final byte[] CF = "cf".getBytes();
public static final byte[] ATTR = "attr".getBytes();
...
Table table = ... // instantiate a Table instance
Scan scan = new Scan();
scan.addColumn(CF, ATTR);
scan.setRowPrefixFilter(Bytes.toBytes("row"));
ResultScanner rs = table.getScanner(scan);
try {
for (Result r = rs.next(); r != null; r = rs.next()) {
// process result...
}
} finally {
rs.close(); // always close the ResultScanner!
}
!请注意,为扫描指定特定停止点的最简单方法是使用InclusiveStopFilter类。
2.4 delete
delete,从表中删除一行,通过table.delete执行,Hbase在物理层面不会立刻删除数据,而是通过创建标记的形式来判别数据是否删除,等到major compaction的时候再将flag=删除的数据进行清理操作。
table.delete(new Delete()...)