HBase(四) HBase JAVA API - Schema操作
Schema操作
表
表描述通过HTableDescriptor对象描述。属性可以通过setter方法设置。
表名
setName(byte[] name)
				
表名不能以.或-开头,只能包含字母和数字,一般在构造函数就设置。
				
表名会作为存储系统中存储路径的一部分来使用,因此必须要符合文件名规范。
				
列族
addFamily(HColumnDescriptor family)
文件大小设置
setMaxFileSize(long maxFileSize)
				
这个参数设置表的region大小,方法名有问题,并不直观,事实上是每个存储单元的大小限制。如果一个列族的存储单元已用空间超过大小限制,region会产生拆分。默认是256M。
				
当表的数据量非常大的时候,可以适当调高这个参数。
				
这个参数是个预期值,可能实际大小会超过这个设置。比如,参数为10M,然后插入了一行20M数据,由于一行数据不能跨region存储,所以也就不会被拆分
				
只读
setReadOnly(boolean readOnly)
				
默认所有表都可以写,特殊时候可以设置只读
				
memstore flush大小
setMemStoreFlushSize(long memstoreFlushSize)
				
Hbase内存中预留了写缓存区,写操作会写入缓冲区,然后按条件触发顺序写入文件,这个过程是flush的过程。
				
这个参数默认为64MB,参数越大,生成的存储文件越大,文件数量越小,同时也导致更长时间的阻塞时间。这时候region server不能持续接收新的数据,请求被阻塞的时间也响应增加。同时,系统崩溃时,WAL恢复的时间也增加。
				
延时日志写
setDeferredLogFlush(boolean isDeferredLogFlush)
				
Hbase有两种把WAL保存磁盘的方式,一种是延时日志写,即deferred log flushing。另一种相反。这个参数默认是false。
				
任意键值设置
setValue(String key, String value)
				
setValue(byte[] key, byte[] value)
				
setValue(ImmutableBytesWritable key, ImmutableBytesWritable value) 
				
这些数据保存在预定义的表里,可以被查询,可以通过加载协处理器的方式进行查询。内部使用ImmutableBytesWritable 类型存储,目的是为了能够序列化。
				
列族
列族通过HColumnDescriptor对象描述。这也是个失败的命名,叫做HFamilyDescriptor恐怕更好。列族定义所有列的共享信息,并且可以通过客户端创建任意数量的列,通常定义某列都要和列族名合并在一起,中间用:分割,即family:qualifier。列族名也必须是可见字符,因为也是要在底层存储系统中使用的,列族会映射到独立的存储文件。
				
Hbase虽然支持空列名,但是一开始就该制定列名的,因为后期无法简单的重命名空列。
				
同表一样,列族也有一系列的属性可以设置:
				
列族名
一般在构造函数中传入,因为列族不能被重命名。如果需要,通常是新建一个列族,然后复制数据到新的列族。
最大版本数
setMaxVersions(int maxVersions)
				
限定了每个值能保留的最大版本数量。Hbase会删除超过最大版本的数据。默认是3,如果不需要访问旧数据,也可以设置为1.
				
压缩
setCompactionCompressionType(Compression.Algorithm type)
				
setCompressionType(Compression.Algorithm type)
				
Hbase支持插件式的压缩算法,默认是”不压缩”,即Compression.Algorithm. NONE 。其他选项有GZ ,LZ4 ,LZO ,SNAPPY ,除了GZ使用本地库或java库,其他需要相关类库支持。
				
块大小
setBlocksize(int s) 
				
Hbase的存储文件被划分为若干个小存储块,这些块在get或scan会被加载到内存中,类似于Oracle中的块。默认大小是64KB。这里列族的块,不同于HDFS的块,也没有依赖
				
开启块缓存
setBlockCacheEnabled(boolean blockCacheEnabled) 
				
Hbase顺序读取一个数据块到内存缓存中,其读取相邻的数据时就可以在内存中读取而不需要查询磁盘,可以有效减少IO。参数默认为true,即每次读取的块都会缓存到内存中。
				
但是如果只需要块中的某个部分,比如特定顺序访问列族,需要设为禁用
				
保存时间TTL
setTimeToLive(int timeToLive) 
				
相对于版本数的另一种判断数据删除的方法。TTL设置了一个基于时间戳的临界值,Hbase会自动检查TTL是否达到上限,在major合并的时候,TTL超时的数据会被删除。参数单位是秒,默认值是Integer.MAX_VALUE,可以理解为默认为永久保存。
				
列族缓存
setInMemory(boolean inMemory)
				
默认为false。注意,设置为true也不意味着列族的所有存储块都会加载到内存中,也不意味着会长期保存,这只是一种高优先级的承诺。在正常数据读的过程中,块数据会被加载到缓存中并长期保存在内存,除非heap压力过大,才会强制从内存移除这部分数据。
				
这个参数适合数据量比较小的列族,如常用的、检索频繁的信息。
				
Bloom过滤器
setBloomFilterType(StoreFile.BloomType bt) 
				
默认是关闭状态,即StoreFile.BloomType. NONE。其他可选项为ROW(Bloom enabled with Table row as Key)、ROWCOL(Bloom enabled with Table row & column (family+qualifier) as Key)。
				
由于列的数量一般多于行(除非每行只有一列),所以ROWCOL选项会占用大量的空间,但是粒度会更细,使用时需要考量。
				
复制范围
setScope(int scope) 
				
hbase提供replication功能,能跨集群同步。本参数默认为0,即关闭状态。还有个选项就是1,即开启状态。其实更像一个bool参数
				
代码示例
                    public static void main(String[] args) throws Exception {
                    
  Configuration conf = HBaseConfiguration.create();
                    
  HBaseAdmin admin = new HBaseAdmin(conf);
                    
  // 这个是隐式的实现,客户端不能显示的调用,是框架在特殊情况下隐式调用
                    
  // admin.abort("cause", new Exception());
                    
  byte[] tableName = Bytes.toBytes("t2");
                    
  // 简单建表
                    
  HTableDescriptor tableDesc = new HTableDescriptor(tableName);
                    
  HColumnDescriptor f1 = new HColumnDescriptor("f1");
                    
  tableDesc.addFamily(f1);
                    
  admin.createTable(tableDesc);
                    
  System.out.println(admin.tableExists(tableName));
                    
  System.out.println(admin.isTableAvailable(tableName));
                    
  // 修改表结构,添加一个列族
                    
  HColumnDescriptor f2 = new HColumnDescriptor("f2");
                    
  tableDesc.addFamily(f2);
                    
  // 禁用状态才能修改表结构
                    
  // 表禁用时,region服务器会将内存中还未提交的已修改数据刷入磁盘,然后关闭所有region,并更新这表的元数据,标记下线
                    
  // 表禁用可能会费时,时长取决于多少数据还在内存中未flush到磁盘
                    
  admin.disableTable(tableName);
                    
  admin.modifyTable(tableName, tableDesc);
                    
  System.out.println(admin.getTableDescriptor(tableName));
					
  admin.deleteColumn("t2", "f1");
                    
  System.out.println(admin.getTableDescriptor(tableName));
                    
  f2.setCacheDataOnWrite(true);
                    
  admin.modifyColumn(tableName, f2);
                    
  System.out.println(admin.getTableDescriptor(tableName));
                    
  admin.addColumn(tableName, f1);
                    
  System.out.println(admin.getTableDescriptor(tableName));
                    
  // 启用在转移表的region到其他可用服务器的场景也比较有用
                    
  admin.enableTable(tableName);
                    
  // 删除表前也要禁用,删除启用的表会抛异常。表被删除,数据也同时被删除
                    
  admin.disableTable(tableName);
                    
  admin.deleteTable(tableName);
                    
  System.out.println(admin.tableExists(tableName));
                    
  // 建表同时预分区,表创建的时候就划分若干个特定的region,分别是起始、终止行健和region数,region数要大于3
                    
  admin.createTable(tableDesc, Bytes.toBytes(1l), Bytes.toBytes(100l), 10);
                    
  printTableRegions(tableName, admin);
                    
  admin.disableTable(tableName);
                    
  admin.deleteTable(tableName);
                    
  // 预分区的另一种方式,直接给出已拆分好的region边界列表
                    
  // 上面的方法起始就是先调用Bytes.split()方法计算出边界,然后调用这种方式而已
                    
  byte[][] regions = new byte[][] { Bytes.toBytes("A"), Bytes.toBytes("D"), Bytes.toBytes("G"),
            Bytes.toBytes("K"), Bytes.toBytes("O"), Bytes.toBytes("T") };
					
  admin.createTable(tableDesc, regions);
                    
  printTableRegions(tableName, admin);
                    
  admin.disableTable(tableName);
                    
  admin.deleteTable(tableName);
                    
  // 异步建表,内部实现中,上面的同步模式就是异步的简单封装,循环不断检查这个任务是否完成
                    
  admin.createTableAsync(tableDesc, regions);
                    
  // 关闭HBaseAdmin实例所有资源,包括与远程服务器的连接
                    
  admin.close();
                    
  }
                    
  private static void printTableRegions(byte[] tableName, HBaseAdmin admin) throws IOException {
                    
  System.out.println("Printing regions of table: " + Bytes.toString(tableName));
                    
  List
  System.out.println("region cnt: " + hrlList.size());
                    
  
                    
  // 下面输出可以看到hbase设计region边界的规则 第一个region的起始行健和最后一个region的终止行健都是空字节
                    
  // 前一个region的终止行健与后一个region的起始行健是相同的 终止行健不包含在region内,而起始行健包括,描述为[ )
                    
  // 样例输出: start key: , end key: 1 start key: 1, end key: 13 …… start key:
                    
  // 85, end key: 100 start key: 100, end key:
                    
  
                    
  for (HRegionLocation hrl : hrlList) {
                    
   HRegionInfo ri = hrl.getRegionInfo();
					
  byte[] sk = ri.getStartKey();
                    
   byte[] ek = ri.getEndKey();
                    
  System.out.println(" start key: " + (sk.length == 8 ? Bytes.toLong(sk) : Bytes.toString(sk))
                + ", end key: " + (ek.length == 8 ? Bytes.toLong(ek) : Bytes.toString(ek)));
                    
   }
					
   }
                
- 点赞
 - 收藏
 - 关注作者
 
            
           
评论(0)