HBase表的设计(一)

HBase表模式的设计

 对于HBase表,在设计表结构之前,我们需要先考虑的几个问题:

  • 这个表应该有多少个列族?
  • 列族使用的是什么数据?
  • 每个列族应该有多少列?
  • 列名应该是什么?尽管列名不必在建表的时候定义,但是后期读写数据时是需要知道的。
  • 单元存放什么数据?
  • 每个单元存储多少个时间版本?
  • 行健结构是什么?应该包含什么信息?

模式影响到表结构和如何读写表,所以说把这些放到宽泛的模式设计中变得尤为重要。

一、HBase的存储方式

  HBase底层物理存储是基于HDFS,在HDFS上是以HFile的形式进行存储的:

  • 表中的列族在HDFS上是以HFile的形式存在,一个HFile对应一个列族,但是一个列族可能会对应多个HFile。
  1.   

一个特定的列族的所有数据在HDFS上会有一个物理存储,这个物理存储区可能会有多个HFile组成,理论上可以通过合并来得到一个HFile,一个列族的所有列在硬盘上是存放在一起的,使用这个特性,可以把不同模式的列放在不同的列族,以便隔离他们。这也是HBase面相列族存储的原因。

二、宽表与高表

  • 宽表:

  HBase中所谓的宽表,指的是表中行少而列多,也就是说一行当中包含有很多的列,但是表整体行很少,比如一张表中行健一共有100个,但是每个行健所包含的列有1000个,这种就是所谓的宽表。

  • 高表 

   HBase中所谓的高表,恰好与宽表相反,行多,列少。比如一张表中行有100万条,而每行对应的列却又10个,这既是所谓的高表。

三、HBase的访问时间复杂度

  为了便于描述,先定义以下变量:

  •   n = 表中KeyValue条目数量(包括Put的结果和Delete留下的墓碑标记)
  •   b = HFile中数据块的数量(HFile Block)
  •   e = 平均一个HFile中一个KeyValue条目的数量(如果知道行的大小,可以进行计算出来)
  • c = 每行中列的平均数量

  先定义针对指定行健查找相关HFile数据块需要的时间。无论是在单行上执行get(),还是为一次扫描查找起始键,都会有这个动作。

  第一步、客户端需要先找到正确的HRegionServer和region。需要花费3次固定运算找到正确的region,1、查找zk,2、查找-ROOT-,3、查找.META.这是一次O(1)的运算。

  在指定region上,行在读的过程中可能存在于两个地方,如果还没有刷写到磁盘就位于memStore,如果已经刷鞋,则位于一个HFile中。假定只有一个HFile,这一行要么在文件中,要么还没刷写,在MemStore中。

  如果用e代表在任意合理的时间在MemStore的条目数量。

    如果一行在MemStore中,因为MemStore是用跳表实现的。所以查找行的时间复杂度是O(log e)。

    如果一行已经刷到磁盘上了,那么就需要先找到正确的HFile数据块。数据块索引是排过序的,所以查找正确的数据块是一次时间复杂度为O(log b)的运算。查找行里的KeyValue对象是在数据块里的一次线性扫描操作。在找到第一个KeyValue对象之后,随后查找剩下的对象就是一次线性扫描。

    假设行里的单元都在同一个数据块中,扫描的时间复杂度是O(e/b)。

    如果行里的单元不在同一个数据块中,这种扫描需要访问多个连续的数据块里的数据,所以这时的运算有读取的行数决定,时间复杂度是O(c)。

    也就是说这种扫描的时间复杂度是O(Max(c,e/b))

所以在访问HBase中的数据时,决定性因素是扫描HFile数据块找到相关KeyValue对象所花费的时间。如果是宽行的话,扫描过程中会增加处理整行的开销。以上的这些分析都是基于在知道行健的情况下。

  如果不知道行健的话,就需要扫描整个区间(有可能是整张表)来查找你关心的行,而这个时间复杂度是O(n)

这里没有讨论关于硬盘寻道的开销。如果需要从HFile里读取的数据已经被加载进数据缓存中,前面的分析是正确的。因为行健是所有这些索引的决定性因素,所以结论是:访问宽行要比访问窄行开销大。

四、rowkey的散列

  HBase的rowkey在设计的时候我们一般都要对其进行散列处理,这样做有以下几个好处:

  • 可以得到定长的行健,即行健的长度是同一的,可以更好的预测读写性能
  • 可以在扫描表的时候可以方便的设置起始域停止键
  • 有助于数据更均匀的分部在region上。减轻或避免发生热点问题

热点:负载极度集中在一小部分的region上。因为负载没有分散的整个集群上,这是不合理的。服务这些region的几台机器承担了绝大部分的工作,将成为整体性能的拼劲。

  对rowkey散列,虽然在所有region上实现了一个均匀的分部,但是这样的话就会失去数据的顺序。换句话说,就是不能在扫描一个小的时间范围。要么扫描整个表(scan),要么获取指定的行(get()或get(List))

  散列和MD5:

    散列函数是把编程的巨长数值映射到定长的小数值上的一种函数。散列算法有很多种,MD5就是其中的一种,也是比较常用的一种。MD5对任何数据进行散列运算生成一个128位(16字节)的散列值。这是一种流行的散列函数,通常生产中,我是对rowkey进行16位的MD5操作。

五、目标数据的访问(重点:索引)

  之前谈到关于HBase的高表与宽表,高表有利于快速得到正确的行。而宽表则有利于进行批量写操作。

  对于HBase中的索引来说,只有键才可以建立索引(KeyValue对象的key部分,包括行健,列限定符和时间戳),可以将其看作是关系型数据库的主键,但是不能够改变构成主键的列,这里的键是由3个元素复合而成的(行健,列限定符和时间戳)。

  在列限定符和时间戳上建立索引,可以在一行上不用扫描前面所有的列而直接跳到正确的列。取回的KeyValue对象基本上来自于HFile的一行。

  从表中获取数据的方式有两种,get和scan。如果只是需要获取指定的某行或这个某几行,也就是说在明确知道行健的情况下,建议使用get或get<List>的方式进行获取。

  如果知道起始键和停止键,则可以使用scan的方式来限制扫描器扫描的的行数进行获取数据。

  在get对象中,可以指定列族和列限定符。当指定列族之后,可以限制客户端只访问指定列族的HFile;当时指定列限定符之后不会限制从硬盘中读出的HFile,只是可以限制网络上传回给客户端的东西。如果给定的region上一个列族存在多个HFile。要查找get()调用里指定的行的内容,不管有多少个HFile包含与请求有关的数据,都要访问所有的HFile。但是get里尽可能的明确查找内容是有必要的,因为不必在网络上传回客户端不需要的数据。唯一的开销也就是RegionServer上可能的硬盘IO,同样,如果get中指定时间戳的话,可以避免读取早于时间戳的HFile。

六、小结

  • HBase表很灵活,可以用字符数组形式存储任何东西
  • 同一列族中存储相似访问模式的东西
  • 索引是建立在KeyValue对象的Key部分上,Key是由行健,列限定符合时间戳按次序组成
  • 高表可能支持将运算复杂度降到O(1),但是要在原子性上付出代价
  • 设计HBase模式的时候进行范规范化处理是一种可行的办法
  • HBase不支持跨行事务,要避免在代码中维护这种复杂的逻辑
  • 散列支持定长键和更均匀的数据分部,但是失去了排序的好处
  • 列限定符可以用来存储数据,就像单元一样
  • 可以将数据放入到列限定符中,所以它的长度会影响到存储空间,当访问数据时,也影响了硬盘和网络IO的开销,所以尽量简练
  • 列族名字的长度会影响通过网络传回客户端的数据大小,所以,也尽量简练

原文地址:https://www.cnblogs.com/Gxiaobai/p/12180223.html

时间: 2024-08-30 03:41:24

HBase表的设计(一)的相关文章

Hbase表的设计

1. 表的设计 1.1 Pre-Creating Regions 默认情况下,在创建HBase表的时候会自动创建一个region分区,当导入数据的时候,所有的HBase客户端都向这一个region写数据,直到这个region足够大了才进行切分.一种可以加快批量写入速度的方法是通过预先创建一些空的regions,这样当数据写入HBase时,会按照region分区情况,在集群内做数据的负载均衡. 下面是一个例子: public static boolean createTable(HBaseAdmi

hbase 表的设计与其它大数据框架的集成

一:hbase 表的设计管理 二:hbase hive 集成 三:sqoop 与hbase 的集成 四:hbase 与hue 集成 五:hbase 表的修复 一:hbase 表的设计管理 1.1 hbase 的shell 命令 1.1.1 创建一个命名空间 在新版本的hbase 中 表是存储在命名空间当中,默认的命名空间是default 创建一个命名空间: create_namespace 'ns2' 查看有多少个命名空间: list_namespace 在命名空间中建立表: create 'n

HBase表的设计(二)之行健的设计

HBase行健的设计 在设计HBase表的时候,行健是唯一重要的事情.应该基于预期的访问模式来为行健进行建模 行健决定了访问HBase表时可以得到的性能.这个结论根植于两个事实: 1.region基于行健为一个区间的行提供服务,并且负责区间内的每一行. 2.HFile在硬盘上存储有序的行. 当region刷写留在内存中的行时生成了HFile,此时这些行已经经过排序了,也会有序的刷写到硬盘上.HBase表的有序特性和底层的存储格式也可以让我们根据如何设计行健以及吧什么放入列限定符来推理性能表现.

HBase表设计

1.Column Family 由于Hbase是一个面向列族的存储器,调优和存储都是在列族这个层次上进行的,最好使列族成员都有相同的"访问模式(access pattern)"和大小特征. 在一张表里不要定义太多的column family.目前Hbase并不能很好的处理超过2~3个column family的表.因为某个column family在flush的时候,它邻近的column family也会因关联效应被触发flush,最终导致系统产生更多的I/O. 2.Row Key 1

hbase表设计优化原则 ***** 生产环境中使用小结

2019/2/28 星期四 hbase表设计优化原则 https://www.cnblogs.com/qingyunzong/p/8696962.html表设计1.列簇设计 追求的原则是:在合理范围内能尽量少的减少列簇就尽量减少列簇. 最优设计是:将所有相关性很强的 key-value 都放在同一个列簇下,这样既能做到查询效率 最高,也能保持尽可能少的访问不同的磁盘文件. 以用户信息为例,可以将必须的基本信息存放在一个列族,而一些附加的额外信息可以放在 另一列族.2.RowKey 设计 HBas

HBase原理和设计

一篇不错的介绍HBase基本原理的文章,转载自:http://www.sysdb.cn/index.php/2016/01/10/hbase_principle/ ,感谢原作者. 简介 HBase —— Hadoop Database的简称,Google BigTable的另一种开源实现方式,从问世之初,就为了解决用大量廉价的机器高速存取海量数据.实现数据分布式存储提供可靠的方案.从功能上来讲,HBase不折不扣是一个数据库,与我们熟悉的Oracle.MySQL.MSSQL等一样,对外提供数据的

【转】HBase原理和设计

简介 HBase —— Hadoop Database的简称,Google BigTable的另一种开源实现方式,从问世之初,就为了解决用大量廉价的机器高速存取海量数据.实现数据分布式存储提供可靠的方案.从功能上来讲,HBase不折不扣是一个数据库,与我们熟悉的Oracle.MySQL.MSSQL等一样,对外提供数据的存储和读取服务.而从应用的角度来说,HBase与一般的数据库又有所区别,HBase本身的存取接口相当简单,不支持复杂的数据存取,更不支持SQL等结构化的查询语言:HBase也没有除

hbase 利用rowkey设计进行多条件查询

摘要 本文主要内容是通过合理Hbase 行键(rowkey)设计实现快速的多条件查询,所采用的方法将所有要用于查询中的列经过一些处理后存储在rowkey中,查询时通过rowkey进行查询,提高rowkey的利用率,加快查询速度.行键(rowkey)并不是简单的把所有要查询的列的值直接拼接起来,而是将各个列的数据转成整型(int)数据来存储.之后实现两个自定义的比较器(comparator):一个是相等比较器,用于实现类似于SQL的多条件精确查找功能. select * from table wh

【HBase】Rowkey设计【转】

本章将深入介绍由HBase的存储架构在设计上带来的影响.如何设计表.row key.column等等,尽可能地使用到HBase存储上的优势. Key设计 HBase有两个基础的主键结构:row key和column key.它们分别用来表征存储的数据和数据的排序顺序.以下的几节将讨论如何通过key设计解决存储设计中发现的一些问题. 概念 相比于物理存储,首先谈谈表的逻辑结构.与传统的面向列的关系型数据库为基本单元不同,HBase的基本存储单元为列簇(column family).从图9-1可以看