Hbase表结构设计

《Hbase表结构设计》
《Hbase表结构设计》
图片来自HBase企业应用…书籍

1 模式创建

1.1 hbase模式结构

    Hbase的模式结构包括表、RowKey、列族、Timestamp(时间版本)。其实模式是一个三维有序结构,前面三个维度确定一行数据。
    Hbase的模式不同于关系型数据库(RDBMS),Hbase的单元格(cell)所在行是有序的,其列(Qualifier)在所属列族(column family)存在的情况下 ,可以通过客户端自由添加。对于这些名词具体含义可以参考另一篇博主写的博客                http://blog.csdn.net/wulantian/article/details/46786413
  我们在设计HBase时候需要考虑不少因素:
    1.这个表应该有多少个列族;
    2.列粗使用什么数据;
    3.每个列族应该有多少列;
    4.列名是什么;
    5.单元应该存放什么数据;
    6.每个单元存储多少个时间版本;
    7.行健(RowKey)结构是什么。应该包含什么信息。

1.2 HBase设计需要注意两个关键点:

(1)join
    Hbase没有join的概念,所以不支持join的操作,但是在不少业务中确需要不少的join操作。而大表结构可以解决这一问题,值需要一条行记录加上一个特定的行关键字,就可以实现把所有的关于join的数据合并在一起。
 (2)RowKey
     RowKey是非常重要的,设计时候需要慎重考虑。如果RowKey是整形的,用二进制的方式应该比string来存储一个数据更加节约空间。以存储用户购买商品为例,复合的RowKey由用户Id作为前缀,倒置的时间串作为RowKey的后缀可以使得我们了解用户最新购买消费信息,我们可以根绝这些推荐用户最近需要什么的产品,经常使用的推荐算法,我们可以根据用户最近的消费商品推荐用户最近还需要购买什么产品。

2 RowKey设计根据实际情况选择优化以下几点

2.1 RowKey按字典顺序从大到小排序

关系型数据库可以在多列上建立索引,但是HBase只能在RowKeya上面建立索引。RowKey是不可分割的字节数,按字典顺序由低到高存储在表中。一个空的数组用来标识空间的起始或者结尾。但是如果我们需要由大到小排列时候我们可以进行转换,最大的变最小,最小的变最大,在应用层转回来即可完成,采用RowKey=Integer.MAX_VALUE-RowKey方式转换。  

2.2 RowKey尽量散列设计

最重要的就是散列的保证,这样就可以保证所有数据都不是在一个Region上,从而避免读写时候负载会集中在个别Region上。假设我们需要存储一个视频网站用户的所有观影记录,这时候的RowKey可以设计成userId_videoId的拼接字符串,但是这样设计的话userId的分布就很肯能不均匀,因为RowKey是按字符串排序的:我们可以采取三种办法解决具体如下:
   (1)反转userId,将其字符串反转后存储;
   (2)散列userId,即对userId进行散列;
   (3)userId取模后MD5加密,取前6位作为前缀加入到userId前面。

2.3 Rowkey的长度尽量要短

如果RowKey过长,第一存储开销会增加,影响存储效率;第二内存中Rowkey字段过长,会导致内存的利用率过低,进而降低索引命中率。一般做法:时间使用Long表示;尽量使用编码压缩。

3 列族(Column Family)

主要讲一下列族的相关配置属性,这些都是有默认值的,在创建表的时候我们也可以显示的指定。列族是一些列的集合。一个列族的所有成员都有着相同的前缀。比如列course:computer和course:english都是列族的成员。:是用来区分前缀跟列名的,列族在创建表时候必须 声明但是列不需要特别声明,用户可以随时创建新列。一个列族的成员在文件系统都存储在一起,因为存储优化针对的是列族。目前HBase不能很好地处理多个列族。
好了下面该说一下列族的相关配置属性了。

3.1 可配置的数据块大小:

HFile数据块大小可以在列族层设置,其默认值是65536字节或者64KB,数据块索引存储每个HFile数据块的起始键,数据块越小索引越大,随机查找性能更好,代码如下:

hbase(main):002:0> create 'mytable'
  {NAME =>'colfam1',BLOCKSIZE=>'65536'}

3.2 数据块缓存:

数据块缓存默认是打开的,可以在新建表或者更改表时候关闭数据块缓存属性,代码如下:
hbase(main):002:0>create'mytable',                             {NAME=>'colfam1',BLOCKCACHE=>'false'}
   IN_MEMORY参数默认值是false,该值表示HBase除了在数据块缓存中保存这列族相比其他列族更激进之外,并不提供其他额外保证,下面展示如何设置的代码:
hbase(main):002:0>create'mytable',                             {NAME=>'colfam1',IN_MEMORY=>'true'}

3.3 布隆过滤器

数据块索引提供了一个有效的方法getDataBlockIndexReader(),在访问某个特定的行时候,用来查找读取的HFile的数据块,但是作用有限。布隆过滤器(Bloom Filter)允许对存储在每个数据块的数据做一个反向测验,当查询某行时先查询布隆过滤器,看看改行是否不在这个数据块,布隆过滤器的两种回答:1,确定的回答行不在;2:不知道。布隆过滤器也可以应用到行内的单元格上,当访问某列的标识符时候先使用同样的反向检验。可以在列族上打开布隆过滤器,默认值是NONE,另外还有两个值ROW表示行级布隆过滤器;ROWCOL表示列标识符级布隆过滤器,代码如下:

hbase(main):002:0>create'mytable',                             {NAME=>'colfam1',BLOOMFILTER =>'ROWCOL'}

3.4 数据压缩

HBase可以使用多种压缩编码,包括LZO、SNAPPY、GZIP。只在硬盘压缩,内存中或者网络传输中没有压缩

hbase(main):002:0>create'mytable',                             {NAME=>'colfam1',COMPRESSION=>'SNAPPY'}

3.5 单元时间版本

时间版本是在列族级设置的,只需要一个时间版本时候,这样子就不会保留更新单元的多个时间版本,代码如下:

hbase(main):002:0>create'mytable',                             {NAME=>'colfam1',VERSIONS=>1}

最小时间版本数,代码如下:

hbase(main):002:0>create'mytable',                             {NAME=>'colfam1',VERSIONS=>5,MIN_VERSIONS => '1'}

同一个建表语句中为列族指定多个属性代码如下:

hbase(main):002:0>create'mytable',                             {NAME=>'colfam1',VERSIONS => 5,TTL=>'18000'}

3.6 生存时间

用于设置单元格的生存周期,单元格过满则会将其删除,在列族cf1上设置TTL为18000s,cf1中超过时间的将会在下一次大合并时候删除。代码如下:

hbase(main):002:0>create'mytable',                             {NAME=>'colfam1',TTL => '18000'}
    原文作者:knowfarhhy
    原文地址: https://blog.csdn.net/u011707542/article/details/53220805
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞