Hbase(四)基本概念

以列作为存储单位进行数据存储,表现就是:一个列为一个存储单元,比如一个列就是一个文件

逻辑结构

RowKey:行键


1.在Hbase中没有主键的概念,取而代之的是行键,相当于关系型数据库中的主键比如id

2.不同于传统的关系型数据库,在HBase中,定义表的时候不需要指定行键列,而是在添加数据的时候来手动添加行键,只要说一下这是个行键列就可以了

3.HBase默认会对行键进行排序,按照字典序排序

Column Family:列族/列簇。

列族(column family)是HBase中最基本的数据结构,它是一组列(column)的集合。列族中的列具有相同的前缀,列族可以理解为一种逻辑上的分组。列族在HBase中有以下几个重要的特点:

列族是HBase中数据存储的基本单位,一个表可以有多个列族。
列族内的列名是有序的,列名的前缀相同,即属于同一个列族。
列族在HBase中的存储结构是有序的,同一列族的数据会被存储在同一块磁盘空间上,这有助于提高读写性能。
列族在HBase中的存储格式是列式存储,即同一列族中的列可以不同时存在,这有助于节省存储空间。

HBase 的逻辑存储视图由行键、时间戳、列族组成一个类似二维表一样的结构,但是在实际存储的时候,数据库存储的数据是以列族为单位进行存储的,是完全将行数据按列族的方式进行分列 

列族与列的关系
列族和列之间的关系是一种包含关系。列族包含了多个列,列具有唯一的列名和列值。在HBase中,列名是由列族名和具体的列名组成的。例如,如果有一个列族名为“user”,那么在这个列族下可以有多个列名,如“name”、“age”、“gender”等。

列族与行(row)的关系
列族和行之间的关系是一种多对一的关系。一个行可以包含多个列族,而一个列族可以包含多个行。在HBase中,行是数据的唯一标识,每个行都有一个唯一的行键(rowkey)。同一个行可以包含多个列族,而同一个列族可以包含多个行。

物理结构

1.在HBase中,没有表关联的概念,取而代之的是用列族来进行统计

2.在HBase中,一个表中至少包含1个列族,可以包含多个列族,理论上不限制列族的数量

3.在HBase中,强调列族,但是不强调列-在定义表的时候必须定义列族,但是列可以动态增删,一个列族可以包含0到多个列

HBase的列级别,分为2个级别

级别1:列族,HBase列式数据库的单元,物理意义上的列。一个列族有独立的数据文件,不同的列族在不同的文件内。
级别2:列(二级列),存在与一个列族的内部

  1. 1个表可以有多个Rowkey,Rowkey是HBase的主键
  2. 每一个Rowkey对应的数据,是一行数据
  3. HBase表在存储上是以列族作为物理的列存在的。(一级列),列族和列族之间,是文件级别的相互隔离。(真正意义的列存储)
  4. 每个列族内部,运行创建多个逻辑的二级列,二级列存在同一个列族文件内。在列族文件内,是行存储。
  5. 每一个二级列对应的数据,都会有自己的时间戳属性。
  6. HBase支持多版本,也就是每一个二级列的数据可以存储多个版本(1个当前最新的 加上 一堆历史老的)
  7. 多版本就是基于 每一个二级列的时间戳属性,来去判断,谁是最新,谁是最老(时间戳越大越新)

namespace:名称空间

在一个项目中,需要使用HBase保存多张表,这些表会按照业务域来划分
为了方便管理,不同的业务域以名称空间(namespace)来划分,这样管理起来会更加容易
类似于Hive中的数据库,不同的数据库下可以放不同类型的表

default名称空间是默认创建表的位置,hbase是专门存放系统表的名称空间(namespace、meta)
管理命名空间指令

在HBase中没有database的概念,取而代之的是namespace

在HBase启动的时候,自带了两个空间:default和hbase。hbase空间下方的是HBase的基本信息;在建表的时候如果不指定,则表默认放在default空间下

# 一、命名空间
# 1.创建一个命名空间
create_namespace 'hello'

# 2.查看命名空间
list_namespace

# 3.删除命名空间
drop_namespace 'hello'

# 4.查看某个具体的命名空间
describe_namespace 'hello'

# 5.在命名空间hello里创建一个名为MSG的表,该表名为a1
create 'hello:MSG','a1'

注:在删除命名空间时要确保空间里没有表,否则会报错

Colum:列


HBase表的列是由列族名、限定符以及列名组成的,其中“:”为限定符。创建HBase表不需要指定列,因为列是可变的,非常灵活。

Timestamp:时间戳


记录每次操作数据的时间,通常记作数据的版本号。数据写到HBase的时候都会被记录一个时间戳,这个时间戳被我们当做一个版本。比如说,我们修改或者删除某一条的时候,本质上是往里边新增一条数据,新增了记录的版本。

hbase在建表的时候,一个列族可以指定一个versions,用以表示所存数据的版本数,默认该值为3,即保存最近的3个版本的数据。在每一个cell中有同一数据的多个版本,按时间倒序排序。我们可以在建表的时候指定versions,在放数据的时候以一个时间戳(一个long值)来表示该数据的版本号。取数据时可以取最新的数据,也可以取特定时间戳的数据,某段时间戳的数据以及全部数据

物理存储结构

在HBase中,每一个列(二级列)的具体数据,都会有时间戳的属性。

如图所示,name和addr两个二级列的具体数据,有各自的时间戳属性。

默认是数据写入HBase的时候,HBase自动做的记录。

HBase中的时间戳是一个64位的long类型数值,用于标识数据的版本。每当向HBase中插入或更新数据时,可以通过指定时间戳来标记数据的版本。

时间戳属性有啥用?

时间戳的属性,在于让HBase的数据可以支持多版本。

多版本的意思是:一个二级列的具体数据,可以有多个版本。

也就是,比如,我们假设一张表,创建的时候,允许5个版本:

列族1的二级列addr,被更新了5次,分别是:

  • 北京(时间戳1)
  • 上海(时间戳2)
  • 深圳(时间戳3)
  • 广州(时间戳4)
  • 杭州(时间戳5)

当我们查询这个具体的二级列的数据,默认返回最新时间戳的那一个,也就是杭州。

如果在来一条数据更新进来,最老的北京将被删除。

二级列的具体数据,有时间戳这个属性,的最大作用就在于,维护多个版本的时候

来判断,谁是老数据,谁是新数据。

建议:如果不需要多版本的功能,那么就不要开启多版本(允许版本数为1即可) 因为多版本,会额外的存储很多数据,多一个版本多一份数据。会间接影响性能(影响不是很大)

HBase的时间戳可以用于以下操作:

  1. 插入数据:当向HBase中插入数据时,可以为每条数据指定一个时间戳。如果不指定时间戳,HBase将使用当前时间作为默认时间戳。可以使用Put类的setTimestamp()方法来设置时间戳。

  2. 更新数据:当更新HBase中的数据时,可以使用相同的row key和列族,但不同的时间戳来插入新的数据版本。HBase会根据时间戳的大小自动选择合适的数据版本。

  3. 读取数据:当从HBase中读取数据时,可以使用时间戳来获取特定版本的数据。可以使用Get类的setTimeStamp()方法来设置要读取的时间戳。如果不设置时间戳,则默认读取最新的数据版本。

  4. 删除数据:可以使用时间戳来删除特定版本的数据。可以使用Delete类的setTimeStamp()方法来设置要删除的时间戳。如果不设置时间戳,则默认删除所有版本的数据。

HBase的数据存储格式


HBase是列式数据库,物理上的存储就是列族对应的文件。

每一个列族对应的文件,我们称之为:HFile

HFile里面存储的是什么呢?

我们以上图的列族1为例,看看内部是如何做数据存储的。

 

如图,我们标记了Rowkey(1,2,3)这三条数据,在HFile中的具体组织形式。

可以看出,HFile本质上内部也是行存储组织。分别有5个列:

  • Rowkey是谁
  • 列族是谁
  • 二级列是谁
  • 时间戳
  • 具体的值

 在HFile中的一条数据 称之为单元格(Cell)

Cell:单元格


根据行键、列族和列可以映射到一个对应的单元格,单元格是HBase存储数据的具体地址。

我们再来举例来解释一下

行式存储

传统的数据库是关系型的,且是按行来存储的。如下图:

 

其中只有张三把一行数据填满了,李四王五赵六的行都没有填满。

因为这里的行结构是固定的,每一行都一样,即使你不用,也必须空到那里,而不能没有。

列式存储

为了与传统的区别,新型数据库叫做非关系型数据库,是按列来存储的。如下图

 我们可以看到原来张三的六列数据变成了现在的六行。原来的六列数据是在一行,所以共用一个主键(即张三)。现在变成了六行,每行都需要一个主键(不然不知道这行数据是谁的),所以原来的主键(即张三)重复了六次

由于原来的列变为了现在的行,如果有需要就加一行,没需要就不加,不会造成空间浪费。

行列对比

行式存储倾向于结构固定,列式存储倾向于结构弱化。 (行式存储相当于套餐,即使一个人来了也给你上八菜一汤,造成浪费;列式存储相等于自助餐,按需自取,人少了也不浪费)
行式存储一行数据只需一份主键,列式存储一行数据需要多份主键。
行式存储存的都是业务数据,列式存储除了业务数据外,还要存储列名。
行式存储更像一个Java Bean,所有字段都提前定义好,且不能改变;列式存储更像一个Map,不提前定义,随意往里添加key/value。

Hbase虽然弱化了结构,但并不等于放任不管。传统关系型数据库在插入数据前表结构(即所有列和列的数据类型)已经是严格确定的。 Hbase的表在放入数据前也有需要确定下来的东西,那就是Column Family(常译为列族/列簇)。

单词Family就是家庭的意思,所以列族就是列的家庭。那么列自然就是家庭成员了,通常家庭成员都有多个,所以一个列族包含多个列。

一个家庭的成员之间具有血缘关系,所以一个列族的多个列之间通常也具有某种关系,比如相似或同种类别。所以列族可以看作是某种分类(归类)。

一个非常常见的例子,去面试的时候,一般前台MM都会让填一张表,通常信息很多,每个公司又不尽相同。但大致可以分三类:人员基本信息,教育经历信息,工作经历信息,这三个类别其实就相当于三个列族。如下图:

每个类别里都会有具体的信息,比如人员基本信息里有姓名、电话、出生年月等,它们就相当于一个个标识符(变量名),在Hbase中叫做Column Qualifier(列修饰符)。列修饰符位于列族里面用来标识一条条数据。如下图:

在Hbase中一个列族(Column Family)和一个列修饰符(Column Qualifier)组合起来才叫一个列(Column),使用冒号(:)分割,列族:列修饰符,如下图:

在传统数据库中每一行的唯一标识符叫做主键,在Hbase中叫做row key(行键)。如下图:

数据在进入Hbase时都会被打上一个时间戳,这个时间戳可以作为版本号来使用。

在t1时间我存入一个人的基本信息,之后发现姓名错了,在t2时间又更新了姓名,此时并不会去更新原来的那条数据,而是又插入了一条新数据且打上新的时间戳。

此时去查询获取的是新数据,仿佛是更新了,但其实只是默认返回了最新版本的数据而已。如下图:

一个行键、列族、列修饰符、数据和时间戳组合起来叫做一个单元格(Cell)。

这里的行键、列族、列修饰符和时间戳其实可以看作是定位属性(类似坐标),最终确定了一个数据。

下图中的一行相等于Hbase中的一个单元格:

一个行键、一到多列(包括数据)组合起来叫做一行(Row)。下图中所有1001的数据合起来相当于Hbase中的一行,1002的相当于另一行:

在Hbase中,只要确定了列族(具体的列不用管),表(Table)就确定了。如下图:

表的设计
列蔟:推荐1-2个,能使用1个就不是使用2个
版本的设计:如果我们的项目不需要保存历史的版本,直接按照默认配置VERSIONS=1就OK。如果项目中需要保存历史的变更信息,就可以将VERSIONS设置为>1。但是设置为大于1也就意味着要占用更多的空间
数据的压缩:在创建表的时候,可以针对列蔟指定数据压缩方式(GZ、SNAPPY、LZO)。GZ方式是压缩比最高的,13%左右的空间,但是它的压缩和解压缩速度慢一些

HBase的KeyValue型存储

KeyValue型(后续简称KV型),在Python中已经使用过。

就是Python的字典。

Python的字典,就是一个键值对(KeyValue)型的数据

d = {"name": "王大大", "age": 11, "addr": "北京"}
上述字典:name、age、addr都是key,王大大、11、北京都是对应key的value
所以
d['name'] 就可以取到王大大,通过key,取value(值)


d = {"info":{"name":"王大大", "age":11},  "score": [11,22,33]}
所以,info和score就是字典的key
通过d['info']就能取到value,也就是一个嵌套的字典
通过d['score']就能取到value,也就是一个嵌套的list
所以,KV,本质上就是一个Key,对应一个Value

HBase就是一个KV型数据库,它有自己的key对应存储的value值。

  • key是一个组合体,由:Rowkey、列族、二级列、时间戳组合而成
  • value,就是一个具体的value(属于某个rowkey的某个列族的某个二级列的某个时间戳)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Allen019

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值