Schema设计原则
Schema创建
HBase schema(模式)可以通过Apache HBase Shell或者Java API Admin来创建或者更新。 进行ColumnFamily(列族)修改时,必须禁用表,例如:
Configuration config = HBaseConfiguration.create();
Admin admin = new Admin(conf);
TableName table = TableName.valueOf("myTable");
admin.disableTable(table);
HColumnDescriptor cf1 = ...;
admin.addColumn(table, cf1);
HColumnDescriptor cf2 = ...;
admin.modifyColumn(table, cf2);
admin.enableTable(table);
Schema更新
当表或者列族被修改时(比如region大小、block大小),这些更改会在下一次major合并、StoreFiles重新写入时生效。
Schema设计经验
HBase存在许多种不同的数据集,具有不同的访问模式和服务层级的要求。因此,以下经验法则只是概述。
- 目标region的大小限制在10GB到50GB之间。
- 限制cell的大小在10MB之内,如果使用的是mob类型,限制在50MB之内。否则,考虑把cell的数据存储在HDFS中,并在HBase中存储指向该数据的指针。
- 典型的scheme每张表包含1到3个列族。HBase表设计不应当和RDBMS表设计类似。
- 对于拥有1或2个列族的表来说,50-100个region是比较合适的。注意region是列族的连续段。
- 保持列族名称尽可能短。每个值都会存储列族的名称(忽略前缀编码)。它们不应该像在典型的RDBMS中一样具有自我记录和描述性。
- 如果正在存储基于时间的机器数据或者日志信息,并且rowkey是基于设备ID或者服务ID+时间,最终可能会出现这样一种情况,即更旧的数据region在某个时间段后永远不会有额外写入。在这种情况下,最终会存在少量的活动region和大量不会再有新写入的region。
HBase列族数量
HBase目前不适合两个或三个列族以上的任何项目,因此应保持模式中的列族数量较少。目前,flushing和compactions是基于每个region进行的,因此如果一个列族承载大量数据带来flushing,则即使它们携带的数据量很小,相邻的族也将被flushing。当存在许多列族时,flushing和compactions可能会产生一堆不必要的I/O。
如果单个表中存在多个列族,请注意基数(即行数)不用相差太大。如果 ColumnFamilyA有100万行而ColumnFamilyB有10亿行,则ColumnFamilyA 的数据可能会分布在许多区域(和RegionServers)中。这使得 ColumnFamilyA的大规模扫描效率降低。
版本数
最大版本数
HBase通过HColumnDescriptor给各列族配置要存储的最大行版本数。最大版本的默认值为1。这是一个重要的参数,因为HBase不会覆盖一个值,只会时间戳来区分值的不同版本。早期的版本会在major compaction过程中被删除。根据应用需求,可以需要增加或减少最大版本的数量。 不建议将最大版本的数量设置为非常高的级别(例如,数百或更多),除非这些旧值非常珍贵,因为这将大大增加StoreFile的大小。
最小版本数
与最大行版本数一样,HBase通过HColumnDescriptor按列族配置要保留的最小行版本数。最小版本的默认值为0,表示该功能已禁用。行版本参数的最小数量与生存时间参数一起使用,并且可以与行版本参数的数量组合,以允许配置诸如“保留最后T分钟的数据,最多N个版本,但至少保留M个版本”(其中M是最小行版本数的值,M<N)。
支持的数据类型
HBase通过Put和Result操作支持“byte-in/bytes-out”接口,因此任何可以转换为字节数组的都可以存储为值。输入可以是字符串、数字、复杂对象、图像,只要它们可以呈现为字节。 值的大小存在实际限制。HBase中的所有行都符合数据模型,包括版本控制。在进行设计时要考虑到这一点,以及列族的块大小。
生存时间
列族可以设置TTL(Time To Live)长度(以秒为单位),HBase将在超时后自动删除行。TTL设置适用于行的所有版本。在HBase中TTL时间为UTC时区。 仅包含过期的行的存储文件,会在minor compaction时删除。将hbase.store.delete.expired.storefile设置为false可禁用此功能。将最小版本数设置为0以外的值也会禁用此功能。
最新版本的HBase还支持按每个cell(单元)设置生存时间。cell TTL使用Mutation#setTTL作为变更请求的一个属性提交。如果设置了TTL属性,则它将应用于被操作更新的所有cell。cell TTL处理和列族TTL之间存在两个显着差异:
- cell TTL以毫秒而不是秒为单位表示。
- cell TTL不能超过列族TTL设置的有效时间。