本文主要介绍schema设计原则。
前提条件
Configuration config = HBaseConfiguration.create();
HBaseAdmin admin = new HBaseAdmin(config);
String table = "Test";
admin.disableTable(table); // 将表下线
HColumnDescriptor f1 = ...;
admin.addColumn(table, f1); // 增加新的列簇
HColumnDescriptor f2 = ...;
admin.modifyColumn(table, f2); // 修改列簇
HColumnDescriptor f3 = ...;
admin.modifyColumn(table, f3); // 修改列簇
admin.enableTable(table);
更新
当表或者列簇改变时(包括:编码方式、压力格式、block大小等等),都将会在下次major compaction时或者StoreFile重写时生效。
表模式设计经验
- 地域最大的阈值取值建议在8GB到50GB之间,不宜过小或过大。
- 单个cell不超过10MB,如果超过10MB,请使用mob,若再大可以直接存在HDFS中,在HBase内存储HDFS地址。
- 列簇数量不建议过多,一般1个即可,不建议超过3个。
- 列簇名应尽量简短,因为存储时每个value都包含列簇名(忽略前缀编码,prefix encoding)。
- 对于时序场景,建议rowkey设计为设备ID加上时间,如果采用“时间+设备ID”的方案会导致如下:
- 同一时间点的数据落入同一个地域,导致热点。
- 较早数据随着时间推移、数据过期会留下大量的空地域,带来不必要的开销。
列簇数量
- 现在HBase并不能很好的处理两个或者三个以上的列簇,所以尽量让列簇数量少一些。
- 目前, flush和compaction操作是针对一个地域。所以当一个列簇操作大量数据的时候会引发一个flush。邻近的列簇也有进行flush操作,尽管它们没有操作多少数据。
- compaction操作现在是根据一个列簇下的全部文件的数量触发的,而不是根据文件大小触发的。
- 当很多的列簇在flush和compaction时,会造成很多没用的I/O负载。
说明 减少没用的I/O负载需要将flush和compaction操作只针对一个列簇。
- 尽量在模式中只针对一个列簇操作。将使用率相近的列归为一列簇,这样每次访问时就只用访问一个列簇,提高效率。
列簇基数
如果一个表存在多个列簇,要注意列簇之间基数(如行数)相差不要太大。例如:列簇A有100万行,列簇B有10亿行,按照行键切分后,列簇A可能被分散到很多地域(及RegionServer),这导致扫描列簇A十分低效。
版本数量
行的版本的数量是HColumnDescriptor设置的,每个列簇可以单独设置,默认是3。这个设置是很重要的,因为HBase不会覆盖一个值,只会在值的后面进行追加描述,用时间戳来区分。过早的版本会在执行major compaction时删除,这些在HBase数据模型有描述。这个版本的值可以根据具体的应用增加或减少。不推荐将版本最大值设到一个很高的水平(100或更多),除非历史数据很重要,因为这会导致存储文件变得极大。
最小版本数
和行的最大版本数一样,最小版本数也是通过HColumnDescriptor在每个列簇中设置的。最小版本数缺省值是0,表示该特性禁用。 最小版本数参数和存活时间一起使用,允许配置如“保存最后T秒有价值数据,最多N个版本,但最少约M个版本”(M是最小版本数,M<N)。该参数仅在存活时间对列簇启用,且必须小于行版本数。
支持数据类型
HBase通过Put和Result支持bytes-in/bytes-out接口,所以任何可被转为字节数组的东西可以作为值存入。输入可以是字符串、数字、复杂对象、甚至图像,它们能转为字节。
存在值的实际长度限制,例如:保存10-50MB对象到HBase对查询来说太长,搜索邮件列表获取本话题的对话。HBase的所有行都遵循HBase数据模型包括版本化。设计时需考虑到以上限制以及列簇的块大小。
存活时间
列簇可以设置TTL秒数,HBase在超时后将自动删除数据,HBase里面TTL时间时区是UTC。
存储文件仅包含有过期的行(expired rows),它们可通过minor compaction删除。将hbase.store.delete.expired.storefile设置为false,可禁用此功能;将最小版本数设置成非0值也可达到同样的效果。
- Cell TTLs的数量级是毫秒而不是秒。
- 一个Cell TTL不能超出ColumnFamily TTLs设置的有效时间。