HBase 的行、列模型
在 HBase 中,数据存储在由行列构成的二维表中。在关系数据库(RDBMS)中,我们也有表的行,列概念。把hbase和Mysql之类的关系型数据库中的概念等价起来,是不对的,不利于理解Hbase的数据模型。
所以,这里的行和列千万不要理解为关系型数据库中的行、列概念。在学习Hbase之前,如果你没有学习过Mysql之类的关系型数据库,那么恭喜你,直接学习Hbase会更容易理解。
HBase 数据模型术语
Hbase中有很多Mysql中没有的概念,我们一起来学习一下吧。
我们先来看看一个图:
结合这张图中出现的概念,我们进一步做一些解释。
表
HBase 表由多行组成。
行
HBase 中的一行由一个行键和一个或多个列组成。
在行存储时,顺序按照字母进行排序。因此,行键的设计非常重要。其目标是以相关行彼此靠近的方式存储数据。
常见的行键模式是网站域名。如果您的行键是域名,则应该反向存储它们(org.apache.www,org.apache.mail,org.apache.jira)。这样,所有 Apache 域名都在表中彼此靠近,而不是基于子域名的第一个字母展开。
这是一个比较好的技巧,一定要记住哦。在关系型数据库中,设计主键的时候,肯和这个相反,希望主键尽可能不一样,从而加速查询速度,但是在hbase中,不存在这个问题。
列
HBase 中的列由 列族和 列限定符组成,它们由:
(冒号)字符分隔。
如:
content:pdf
content是列族,pdf是列限定符。
列族
出于性能原因,列族通常在物理上拥有一簇列及其值。每个列族都有一组存储属性,例如是否应将其值缓存在内存中,如何压缩其数据或对其行键进行编码等。表中的每一行都具有相同的列族,但是列族中存放的信息可能为空。
列限定符
列限定符被添加到列族中,以提供给定数据段的索引。给定列族content
,列限定符可能是content:html
,另一个可能是content:pdf
。虽然列族在创建表时是固定的,但列限定符是可变的,并且行之间可能有很大差异。
单元格
单元格是行,列族和列限定符的组合,它包含一个值和一个时间戳,时间戳表示值的版本。
单元格可以指定一个特定的数据。
时间戳
时间戳与每个值一起写入,它是该值给定版本的标识符。默认情况下,时间戳表示写入数据时 RegionServer 上的时间。当您将数据放入单元格时,可以指定不同的时间戳值。
Hbase逻辑视图
我们来看看Hbase的的逻辑结构:
以下示例是一个Hbase的逻辑结构。我们有一个名为webtable
的表,包含两行(com.cnn.www
和com.example.www
)和三个列族,名为contents
,anchor
和people
。在此示例中,对于第一行(com.cnn.www
),anchor
包含两列(anchor:cssnsi.com
,anchor:my.look.ca
),contents
包含一列(contents:html
)。
此示例包含具有行键com.cnn.www
的行的 5 个版本,以及具有行键com.example.www
的行的一个版本。 contents:html
列限定符包含给定网站的整个HTML。 anchor
列族的限定符每个都包含指向该行所代表的站点的外部站点的链接,以及它在其链接的anchor
中使用的文本。 people
列系列表示与该站点关联的人员。
列名
按照惯例,列名由其列族前缀和*限定符*组成。例如,列 contents:html 由列族
contents
和html
限定符组成。冒号字符(:
)从列族,限定符中分隔列族。
表 webtable
:
行键 | 时间戳 | ColumnFamily contents |
ColumnFamily anchor |
ColumnFamily people |
---|---|---|---|---|
“com.cnn.www” | T9 | anchor:cnnsi.com = "CNN" |
||
"com.cnn.www" | T8 | anchor:my.look.ca = "CNN.com" |
||
"com.cnn.www" | T6 | contents:html = "<html>…" |
||
"com.cnn.www" | T5 | contents:html = "<html>…" |
||
"com.cnn.www" | T3 | contents:html = "<html>…" |
||
“com.example.www” | t5 | contents:html = "<html>…" |
people:author = "John Doe" |
此表中看起来为空的单元格在 HBase 中不占用空间,或实际上不存在。这和关系型数据库有明显的区别,关系型数据库中无论存没有存数据,都会占用空间,这也是HBase“稀疏”的原因。
表格视图不是查看 HBase 中数据的唯一方法,甚至也不是最准确的方法。以下表示与多维映射相同的信息。这只是一个出于演示目的的模型,可能并不完全准确。
我们用Json格式来表示Hbase的结构,会更合适。
{ "com.cnn.www": { contents: { t6: contents:html: "<html>..." t5: contents:html: "<html>..." t3: contents:html: "<html>..." } anchor: { t9: anchor:cnnsi.com = "CNN" t8: anchor:my.look.ca = "CNN.com" } people: {} } "com.example.www": { contents: { t5: contents:html: "<html>..." } anchor: {} people: { t5: people:author: "John Doe" } } }
用json来表示是Hbase更为准备,它就像一个Key-Value映射,将Hbase理解为字典表会更合适。
Hbase物理视图(存储结构)
虽然在概念级别,表可以看作一组稀疏的行,但在物理意义上它们是按照列族存储的。可以随时将新的列限定符(column_family:column_qualifier)添加到现有列族中。
ColumnFamily webtable
:
Row Key | Time Stamp | 列族anchor |
---|---|---|
"com.cnn.www" |
t9 | anchor:cnnsi.com = "CNN" |
"com.cnn.www" |
t8 | anchor:my.look.ca = "CNN.com" |
ColumnFamily contents
Row Key | Time Stamp | ColumnFamily contents: |
---|---|---|
"com.cnn.www" |
t6 | contents:html = "…" |
"com.cnn.www" |
t5 | contents:html = "…" |
"com.cnn.www" |
t3 | contents:html = "…" |
逻辑视图中显示的空单元格不占据物理存储空间。因此,对时间戳t8
处对contents:html
列的值的请求将不返回任何值,因为它没有被存储。
类似地,在时间戳t9
处对anchor:my.look.ca
值的请求将不返回任何值。但是,如果未提供时间戳,则将返回特定列的 最新值。给定多个版本,最新版本也是第一个版本, 因为时间戳按降序存储。
因此,如果没有指定时间戳,则对行com.cnn.www
中所有列的值的请求将是:来自时间戳t6
的contents:html
的值,来自时间戳t9
的anchor:cnnsi.com
的值,来自时间戳t8
的anchor:my.look.ca
。理解本段的意思非常重要,每一个列中的值都是取版本最新的值。