HBase—表结构

HBase—表结构

一,高表与宽表的选择

高表:很多行较少列,即行多列少,一行中的数据量较少,行数大。

宽表:很多列较少行,即列多行少,一行中的数据量较大,行数少。

HBase的 Row Key是分布式的索引,也是分片的依据。

hbase的row key + column family + column qualifier + timestamp + value是HFile中数据排列依据。HFile据此,对数据库的索引到data block级别,而不是行级别。所以这种key是HFile内部的粗粒度(data block粒度)本地索引的主键。

据此,在HBase中使用宽表,高表的优劣总结如下:

---- 查询性能高表更好,因为查询条件都在 row Key中,是分布式索引的一部分。高表的行较多,每行的数据较少,所以查询缓存的BlockCache能缓存更多的行,以列数为单位的吞吐量会更高。

---- 分片能力高表分片粒度更细各个分片的大小更均衡。因为高表的一行数据较少,宽表的一行数据较多,HBase按行来分片的。

---- 元数据开销高表元数据开销更大。高表行多,row key多,可能造成region的数量也较多,-root- , .meta表数据量更大。过大的元数据开销,可能引起HBase集群的不稳定,master更大的负担。

---- 事务能力宽表事务性更好。HBase对一行的写入(Put)是有事务原子性的,一行的所有列要么全部写入成功,要么全部没有写入。但是多行的更新之间没有事务性的保证。

---- 数据压缩比如果对一行数据进行压缩,宽表能获得更高的压缩比。因为宽表中一行的数据量较大,往往存在更多相似的二进制字节,有利用提高压缩比。通过压缩,缓解了宽表一行数据量太大,并导致分片大小不均匀的问题。查询时,我们根据row Key找到压缩的文件,进行解压缩。而且解压缩可以通过协处理器在HBase服务器上做,而不是在业务服务器上做,以充分应用HBase集群的CPU能力。4

设计表时,不能绝对的去追求宽表,高表,而是在两者之间做好平衡。

二,数据块大小选择

数据块小—索引大—占用更大的内存。 (同时加载进内存的数据块越小,随机查找性能就更好)

相反如果需要更好的序列扫描性能,那么一次性加载更多的HFile数据进入内存更为合理。这意味着应该将数据块设置为更大的值。相应的,索引变小,将在随机读性能上付出更多的代价。

​ HFile数据块大小可以在列族层次设置。这个数据块不同于HDFS数据块,默认是65535字节(65KB).数据块索引存储每个HFile数据块的起始键。数据块大小的设置影响数据块索引大小。

hbase(main) :> create 'mytable',{NAME => 'test', BLOCKSIZE='65535'}

三,数据块缓存(OPEN)

把数据放入缓存,并不是一定能够提升性能。如果一个表的列族只能被顺序化扫描访问或很少被访问,则 get scan 操作花费时间长是可以接受。这个情况情况下可以选择关闭列族的缓存。

​ 如果执行多次顺序化扫描(多次使用缓存)并且可能会滥用缓存,从而把应该放入缓存获得性能提升的数据给排挤出去。如果关闭缓存,可以避免上述情况,而且可以让出更多缓存给其他表和同一表的其他列族使用。

数据块缓存默认是打开的。可以新建或更改表时关闭数据块缓存属性:

 hbase(main):>  create 'mytable', {NAME => 'colfam1', BLOCKCACHE => 'false' }

IN_MEMORY 参数的默认值是 false,该值表示HBase除了在数据块缓存中保存这个嫘祖相比其他列族更激进之外,并不提供其他额外保证。该参数在实际应用中设置为true,此时访问的性能不会相差太大。设置 IN_MEMORY:

 hbase(main):>  create 'mytable', {NAME => 'colfam1', IN_MEMORY => 'true'}

四,布隆过滤器(NONE)

​ 布隆过滤器可以应用在块上,检查行键,也可以应用在行内的单元格上,当访问某列表示服时先使用同样的反向检测

​ 布隆过滤器允许对存储在每个数据块的数据做一个反向检测。查询行时,先查询布隆过滤器。(Bloom Filter)。看看该行是否不存在这个数据块, 要么返回该行不存在。要么返回不知道。

​ 如果想要判断一个元素是不是在一个集合里,一般想到的是将所有元素保存起来,然后通过比较确定。链表,树等等数据结构都是这种思路. 但是随着集合中元素的增加,我们需要的存储空间越来越大,检索速度也越来越慢(O(n),O(logn))。不过世界上还有一种叫作散列表(又叫哈希表,Hash table)的数据结构。它可以通过一个Hash函数将一个元素映射成一个位阵列(Bit array)中的一个点。这样一来,我们只要看看这个点是不是1就可以知道集合中有没有它了。这就是布隆过滤器的基本思想。

Hash面临的问题就是冲突。假设Hash函数是良好的,如果我们的位阵列长度为m个点,那么如果我们想将冲突率降低到例如 1%, 这个散列表就只能容纳m / 100个元素。显然这就不叫空间效率了(Space-efficient)了。解决方法也简单,就是使用多个Hash,如果它们有一个说元素不在集合中,那肯定就不在。如果它们都说在,虽然也有一定可能性它们在说谎,不过直觉上判断这种事情的概率是比较低的。

​ 存储这个额外的索引层需要占用额外的空间,占用的大小随着索引对象数据增长而增长。所以行级布隆过滤器比列标识符级布隆过滤器占用空间要小。当空间不是问题时,他们可以压榨整个系统的性能潜力.

可以在列族上打布隆过滤器:

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

NONE 布隆过滤器默认参数 。

ROW 表示 行级布隆过滤器(检查rowkey存不存在);

ROWCOL表示 列标识符级布隆过滤器(检查 rowkey 和 列限定符存不存在)。

五,数据压缩

​ 数据压缩有助于节省磁盘空间,但是读写数据时压缩和解压缩会提高CPU使用率。除非确定压缩不会提升系统的性能,否则推荐打开表的压缩。

​ 只有在数据不能被压缩,或者因为某些原因服务器的 CPU 利用率有限制的情况下,有可能需要关闭压缩特性。

​ HBase使用的压缩编码: SNAPPY拥有 BSD(BSD-licensed)许可,所以它更容易和 Hadoop 及 HBase 发行版捆绑在一起。 LZO 和 SNAPPY 的压缩比例和压缩 / 解压速度差不多。

创建表时可以在列族上打开压缩:

hbase(main)> create 'mytable' , {NAME => 'colfaml' , COMPRESSION => 'SNAPPY'}

数据只在硬盘上是压缩的,在内存中(MemStore 或 BlockCache)或在网络传输时是没有压缩的

数据的压缩编码不能经常改变,如果需要改变某个列族的压缩编码,直接更改表定义,设定新的压缩编码,当Region合并时,生成的 HFile 全部会采用新的编码压缩。这个过程不需要创建新的表和复制数据。

六,单元时间版本和生存空间

如果只需要一个版本,在创建表时可以直接将 vsersion的参数设置为1。时间版本也是列族级的。

hbase(main) > create 'mytable' , { NAME => 'colfaml', VERSION => 1}

可以在同一个建表语句中为列族设置版本和生命周期

hbase(main) > create 'mytable' , { NAME => 'colfaml' , VERSION => 1, TTL => '18000'}    // TTL 值默认是永久保存,(2147483647)单位是秒。  此数校验为 68 年

TTL 生存时间,用于设置单元格的生存周期。如果单元格过期,则会将其删除。早于指定时间的数据会在下一次大合并时将其删除。

猜你喜欢

转载自blog.csdn.net/weixin_43270493/article/details/86532717