HBase有几个高级特性,在你设计表时可使用。这些特性不必定联系到模式或行键设计,可是它们定义了某些方面的表行为。本节咱们讨论这些配置参数,以及你能够如何使用它们。
1 可配置的数据块大小
HFile数据块大小能够在列族层次设置。这个数据块不一样于以前谈到的HDFS数据块。其默认值是65,536字节,或64KB。数据块索引存储每一个HFile数据块的起始键。数据块大小设置影响到数据块索引的大小。数据块越小,索引越大,从而占用更大内存空间。同时由于加载进内存的数据块更小,随机查找性能更好。可是若是你须要更好的序列扫描性能,那么一次可以加载更多HFile数据进入内存则更为合理,这意味着数据块应该设置为更大的值。相应地索引变小,你将在随机读性能上付出代价。
你能够在表实例化时设置数据块大小,以下所示:
hbase(main):002:0> create 'mytable',
{NAME => 'colfam1', BLOCKSIZE => '65536'}
2 数据块缓存
把数据放进读缓存,但工做负载却常常不能从中得到性能提高——例如,若是一张表或表里的列族只被顺序化扫描访问或者不多被访问,你不会介意Get或Scan花费时间是否有点儿长。在这种状况下,你能够选择关闭那些列族的缓存。若是你只是执行不少顺序化扫描,你会屡次倒腾缓存,而且可能会滥用缓存把应该放进缓存得到性能提高的数据给排挤出去。若是关闭缓存,你不只能够避免上述状况发生,并且可让出更多缓存给其余表和同一表的其余列族使用。
数据块缓存默认是打开的。你能够在新建表或者更改表时关闭它:
hbase(main):002:0> create 'mytable',
{NAME => 'colfam1', BLOCKCACHE => 'false’}
3 激进缓存
你能够选择一些列族,赋予它们在数据块缓存里有更高的优先级(LRU缓存)。若是你预期一个列族比另外一个列族随机读更多,这个特性早晚用得上。这个配置也是在表实例化时设定:
hbase(main):002:0> create 'mytable',
{NAME => 'colfam1', IN_MEMORY => 'true'}
IN_MEMORY参数的默认值是false。由于HBase除了在数据块缓存里保存这个列族相比其余列族更激进以外并不提供额外的保证,该参数在实践中设置为true不会变化太大。
4 布隆过滤器(Bloom filters)
数据块索引提供了一个有效的方法,在访问一个特定的行时用来查找应该读取的HFile的数据块。可是它的效用是有限的。HFile数据块的默认大小是64KB,这个大小不能调整太多。
若是你要查找一个短行,只在整个数据块的起始行键上创建索引没法给你细粒度的索引信息。例如,若是你的行占用100字节存储空间,一个64KB的数据块包含(64 * 1024)/100 = 655.53 = ~700行,而你只能把起始行放在索引位上。你要查找的行可能落在特定数据块上的行区间里,但也不是确定存放在那个数据块上。这有多种状况的可能,或者该行在表里不存在,或者存放在另外一个HFile里,甚至在MemStore里。这些状况下,从硬盘读取数据块会带来IO开销,也会滥用数据块缓存。这会影响性能,尤为是当你面对一个巨大的数据集而且有不少并发读用户时。
布隆过滤器容许你对存储在每一个数据块的数据作一个反向测试。当某行被请求时,先检查布隆过滤器看看该行是否不在这个数据块。布隆过滤器要么肯定回答该行不在,要么回答它不知道。这就是为何咱们称它是反向测试。布隆过滤器也能够应用到行里的单元上。当访问某列标识符时先使用一样的反向测试。
布隆过滤器也不是没有代价。存储这个额外的索引层次占用额外的空间。布隆过滤器随着它们的索引对象数据增加而增加,因此行级布隆过滤器比列标识符级布隆过滤器占用空间要少。当空间不是问题时,它们能够帮助你榨干系统的性能潜力。
你能够在列族上打开布隆过滤器,以下所示:
hbase(main):007:0> create 'mytable',
{NAME => 'colfam1', BLOOMFILTER => 'ROWCOL'}
BLOOMFILTER参数的默认值是NONE。一个行级布隆过滤器用ROW打开,列标识符级布隆过滤器用ROWCOL打开。行级布隆过滤器在数据块里检查特定行键是否不存在,列标识符级布隆过滤器检查行和列标识符联合体是否不存在。ROWCOL布隆过滤器的开销高于ROW布隆过滤器。
5 生存时间(TTL)
应用系统常常须要从数据库里删除老数据。因为数据库很难超过某种规模,因此传统上数据库内建了许多灵活处理办法。例如,在TwitBase里你不肯意删除用户在使用应用系统期间生成的任何推帖。这些都是用户生成数据,未来有一天当你执行一些高级分析时可能有用。可是并不须要保存全部推帖用于实时访问。因此早于某个时间的推帖能够归档存放到平面文件里。
HBase可让你在数秒内在列族级别设置一个TTL。早于指定TTL值的数据在下一次大合并时会被删除。若是你在同一单元上有多个时间版本,早于设定TTL的版本会被删除。你能够关闭TTL或者经过设置其值为INT.MAX_VALUE (2147483647)来让它永远打开(这是默认值)。你能够在建表时设置TTL,以下所示:
hbase(main):002:0> create 'mytable', {NAME => 'colfam1', TTL => '18000'}
该命令在colfam1列族上设置TTL为18,000秒=5小时。colfam1里超过5小时的数据将会在下一次大合并时被删除。
6 压缩
HFile能够被压缩并存放在HDFS上。这有助于节省硬盘IO,可是读写数据时压缩和解压缩会抬高CPU利用率。压缩是表定义的一部分,能够在建表或模式改变时设定。除非你肯定不会从压缩中受益,咱们推荐你打开表的压缩。只有在数据不能被压缩或者由于某种缘由服务器的CPU利用率有限制要求的状况下,有可能会关闭压缩特性。
HBase可使用多种压缩编码,包括LZO、Snappy和GZIP。LZO[1]和Snappy[2]是其中最流行的两种。Snappy由Google在2011年发布,发布不久Hadoop和HBase项目开始提供支持。在此以前,选择的是LZO编码。Hadoop使用的LZO原生库受GPLv2版权控制,不能放在Hadoop和Hbase的任何发行版里;它们必须单独安装。另外一方面,Snappy拥有BSD许可(BSD-licensed),因此它更容易和Hadoop和HBase发行版捆绑在一块儿。LZO和Snappy的压缩比例和压缩/解压缩速度差很少。
当建表时你能够在列族上打开压缩,以下所示:
hbase(main):002:0> create 'mytable',
{NAME => 'colfam1', COMPRESSION => 'SNAPPY'}
注意数据只在硬盘上是压缩的。在内存里(MemStore或BlockCache)或网络传输时是没有压缩的。
改变压缩编码的作法不该该常常发生,可是若是你的确须要改变某个列族的压缩编码,直接作就能够。你须要更改表定义,设定新压缩编码。此后合并时,生成的HFile所有会采用新编码压缩。这个过程不须要建立新表和复制数据。但你要确保直到改变编码后全部老HFile被合并后才能从集群中删除老编码函数库。
7 单元时间版本
HBase在默认状况下每一个单元维护三个时间版本。这个属性是能够设置的。若是你只须要一个版本,推荐你在设置表时只维护一个版本。这样系统就不会保留更新单元的多个时间版本。时间版本也是在列族级设置的,能够在表实例化时设定:
hbase(main):002:0> create 'mytable', {NAME => 'colfam1', VERSIONS => 1}
你能够在同一个create语句里为列族指定多个属性,以下所示:
hbase(main):002:0> create 'mytable',
{NAME => 'colfam1', VERSIONS => 1, TTL => '18000'}
你也能够指定列族存储的最少时间版本数,以下所示:
hbase(main):002:0> create 'mytable', {NAME => 'colfam1', VERSIONS => 5,
MIN_VERSIONS => '1'}
在列族上同时设定TTL也是早晚有用的。若是当前存储的全部时间版本都早于TTL,至少MIN_VERSION个最新版本会保留下来。这样确保在你的查询以及数据早于TTL时有结果返回。
[1] Lempel-Ziv-Oberhumer 压缩算法:www.oberhumer.com/opensource/lzo/。
[2] Snappy 压缩函数库,来自于Google:http://code.google.com/p/snappy/。算法