HBase是一个NoSQL数据库,用于处理海量数据。HBase的特点

  1. 大:一个表可以有上亿行,上百万列。
  2. 面向列:面向列表(簇)的存储和权限控制,列(簇)独立检索。
  3. 稀疏:对于为空(NULL)的列,并不占用存储空间,因此,表可以设计的非常稀疏。
  4. 无模式:每一行都有一个可以排序的主键和任意多的列,列可以根据需要动态增加,同一张表中不同的行可以有截然不同的列。
  5. 数据多版本:每个单元中的数据可以有多个版本,默认情况下,版本号自动分配,版本号就是单元格插入时的时间戳。
  6. 数据类型单一:HBase中的数据都是字符串,没有类型。

  首先来了解下HBase的表结构。
  为了更好的理解HBase表的思路,先看一下关系数据库中表的处理方式。例如有一个用户表user_info,有字段:id、name、tel,那么表名和字段需要在建表时指定:

create table user_info (
    id 类型,
    name 类型,
    tel 类型
)

然后插入数据:
insert into user_info values(...)
此时表结构如下:

id

name

tel

1

小明

123

2

小王

456

后来字段不够用了,新用户需要记录地址,就要新增一个字段:

id

name

tel

addr

1

小明

123

2

小王

456

以后再增加需求时,就继续新增字段,或者添加一个扩展表。

  下面看一下HBase的处理方式,HBase建表时要指定的是:表名、列族。建表语句
create 'user_info', 'base_info', 'ext_info'
意思是新建一个表,名称是user_info,包含两个列族base_info和ext_info。列族是列的集合,一个列族中包含多个列,这时的表结构:

row key

base_info

ext_info




插入一条用户数据:name为‘a’,tel为‘123’,插入语句

put 'user_info', 'row1', 'base_info:name', 'a'
put 'user_info', 'row1', 'base_info:tel', '123'

意思是向user_info表中行键为row1base_info列族中添加一项数据 name:a,接着又添加一项数据tel:123。name和tel就是具体字段,属于base_info这个列族
  这时的表结构:

row key

base_info

ext_info

row1

name:a, tel:123

再插入一条数据:name为‘b’,addr为‘beijing’:

put 'user_info', 'row2', 'base_info:name', 'b'
put 'user_info', 'row2', 'ext_info:addr', 'bj'

  这时的表结构:

row key

base_info

ext_info

row1

name:a, tel:123

row2

name:b

addr:bj

到此大致对HBase的表结构有了个初步的认识。


HBase数据模型中一些名词的概念:
  表(Table): HBase会将数据组织进一张张的表里面,但是需要注意的是表名必须是能用在文件路径里的合法名字,因为HBase的表是映射成hdfs上面的文件。
  行(Row): 在表里面,每一行代表着一个数据对象,每一行都是以一个行键(Row Key)来进行唯一标识的,行键并没有什么特定的数据类型,以二进制的字节来存储。
  列族(Column Family): 在定义HBase表的时候需要提前设置好列族, 表中所有的列都需要组织在列族里面,列族一旦确定后,就不能轻易修改,因为它会影响到HBase真实的物理存储结构,但是列族中的列标识(Column Qualifier)以及其对应的值可以动态增删。表中的每一行都有相同的列族,但是不需要每一行的列族里都有一致的列标识(Column Qualifier)和值,所以说是一种稀疏的表结构,这样可以一定程度上避免数据的冗余。
  列标识(Column Qualifier): 列族中的数据通过列标识来进行映射,其实这里可以不用拘泥于“列”这个概念,也可以理解为一个键值对,Column Qualifier就是Key。列标识也没有特定的数据类型,以二进制字节来存储。
  单元(Cell): 每一个行键,列族和列标识共同组成一个单元,存储在单元里的数据称为单元数据,单元和单元数据也没有特定的数据类型,以二进制字节来存储。
  时间戳(Timestamp): 默认下每一个单元中的数据插入时都会用时间戳来进行版本标识。读取单元数据时,如果时间戳没有被指定,则默认返回最新的数据,写入新的单元数据时,如果没有设置时间戳,默认使用当前时间。每一个列族的单元数据的版本数量都被HBase单独维护,默认情况下HBase保留3个版本数据。


存储类型
  TableName 是字符串
  RowKey 和 ColumnName 是二进制值(Java 类型 byte[])
  Timestamp 是一个 64 位整数(Java 类型 long)
  value 是一个字节数组(Java类型 byte[])。

存储结构
  可以简单的将HTable的存储结构理解为

SortedMap (
    RowKey, List (
        SortedMap (
            Column, List (
                Value, Timestamp
            )
        )
    )
)

即HTable按Row key自动排序,每个Row包含任意数量个Columns,Columns之间按Column key自动排序,每个Column包含任意数量个Values。理解该存储结构将有助于查询结果的迭代。

  下图可以帮助理解一下存储结构:

hbase字段不存在和字段null hbase表字段类型_数据