表设计
HBase的表设计会直接影响到HBase的使用效率和便利性,并且一旦结构确定下来之后很难修改
HBase的表设计主要包括行键设计和列族设计
HBase表中的列族设计
列族不宜过多,越少越好,官方推荐不要超过3个,列族过多,会造成Hregion中Store的数量很多,造成memStore过多,耗费大量内存空间。
经常要一起查询的数据不要放在不同的列族中,尽量减少跨列族的数据访问跨列族查询数据,意味着底层的查询过程,需要经历多个Store,浪费时间(一个列族对应一个Store)
如果真的要设计多个列族,要提前考虑好列族数据不均匀的问题;防止由于列族之间的数据量不均匀,造成在region分裂的过程中,某些region越切越小,影响后续查询效率
HBase表中的行键的设计
行键设计的基本原则
-
行键必须唯一,必须唯一才能唯一标识数据
-
行键必须有意义,这样才能方便数据的查询
-
行键最好是字符串类型,因为数值类型在不同的系统中处理的方式可能不同
-
行键最好具有固定的长度,不同长度的数据可能会造成自然排序时排序的结果和预期不一致
-
行键不宜过长,行键最多可以达到64KB,但是最好是在10~100字节之间,最好不要超过16字节,越短越好,最好是8字节的整数倍。
行键设计的最佳实践
-
散列原则:
行键的设计将会影响数据在hbase表中的排序方式,这会影响region切分后的结果,要注意,在设计行键时应该让经常被查询的热点数据分散在不同的region中,防止某一个或某几个regionserver成为热点。
-
有序原则:
行键的设计将会影响数据在hbase表中的排序方式,所以一种策略是通过设计行键将将经常连续查询的数据排列在一起,这样一来可以方便批量查询
应该权衡自己的需求,决定使用散列原则还是有序原则
案例
列族设计为一个列族
行键设计:
- 唯一,使用random函数保证唯一
- 有意义,random_time_host_age
- 最好是字符串 “random_time_host_age”
- 具有固定的长度,“rand[28-8]_time[10]_host[5-25]_age[2]”
- 行键不宜过长,10<48<100 且是8的倍数
- 选择散列原则或者是有序原则 “time[10]_host[5-25]_age[2]_rand[28-8]”
结果:
JavaAPI操作HBase
//创建表
@Test
public void create() throws Exception{
//1.创建HBaseAdmin
Configuration conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "hadoop01:2181,hadoop02:2181,hadoop03:2181");
HBaseAdmin admin = new HBaseAdmin(conf);
//2.创建表
HTableDescriptor tabDesc = new HTableDescriptor(TableName.valueOf("tabx1"));
HColumnDescriptor cf1Desc = new HColumnDescriptor("cf1".getBytes());
tabDesc.addFamily(cf1Desc);
HColumnDescriptor cf2Desc = new HColumnDescriptor("cf2".getBytes());
tabDesc.addFamily(cf2Desc);
admin.createTable(tabDesc);
//3.关闭连接
admin.close();
}
//插入数据
@Test
public void put() throws Exception{
//1.创建HTable
Configuration conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "hadoop01:2181,hadoop02:2181,hadoop03:2181");
HTable tab = new HTable(conf, "tabx1");
//2.写入数据
Put put = new Put("rk1".getBytes());
put.add("cf1".getBytes(), "c1".getBytes(), "v1111".getBytes());
tab.put(put);
//3.关闭连接
tab.close();
}
//获取数据
@Test
public void get() throws Exception{
//1.创建HTable
Configuration conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "hadoop01:2181,hadoop02:2181,hadoop03:2181");
HTable tab = new HTable(conf, "tabx1");
//2.获取数据
Get get = new Get("rk1".getBytes());
Result result = tab.get(get);
byte[] value = result.getValue("cf1".getBytes(), "c1".getBytes());
String str = new String(value);
System.out.println(str);
//3.关闭连接
tab.close();
}
//删除数据
@Test
public void delete() throws Exception{
//1.创建HTable
Configuration conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "hadoop01:2181,hadoop02:2181,hadoop03:2181");
HTable tab = new HTable(conf, "tabx1");
//2.删除数据
Delete del = new Delete("rk1".getBytes());
tab.delete(del);
//3.关闭连接
tab.close();
}
学习中,有不正确的地方多多指教