创建二级索引
功能简介
一般都通过调用org.apache.hadoop.hbase.index.client.IndexAdmin中方法进行HBase二级索引的管理,该类中提供了创建索引的方法。
说明:
二级索引不支持修改,如果需要修改,请先删除旧的然后重新创建。
在表上增加二级索引后,不支持对原始表的truncate操作。
代码样例
public void createIndex() {
LOG.info("Entering createIndex.");
String indexName = "index_name";
// Create index instance
IndexSpecification iSpec = new IndexSpecification(indexName);
iSpec.addIndexColumn(new HColumnDescriptor("info"), "name", ValueType.String);//注[1]
IndexAdmin iAdmin = null;
Admin admin = null;
try {
// Instantiate IndexAdmin Object
iAdmin = new IndexAdmin(conf);
// Create Secondary Index
iAdmin.addIndex(tableName, iSpec);
admin = conn.getAdmin();
//Specify the encryption type of indexed column
HTableDescriptor htd = admin.getTableDescriptor(tableName);
admin.disableTable(tableName);
htd = admin.getTableDescriptor(tableName);
//Instantiate index column description.
HColumnDescriptor indexColDesc = new HColumnDescriptor(
IndexMasterObserver.DEFAULT_INDEX_COL_DESC);
//Set the description of index as the HTable description.
htd.setValue(Constants.INDEX_COL_DESC_BYTES,
indexColDesc.toByteArray());
admin.modifyTable(tableName, htd);
admin.enableTable(tableName);
LOG.info("Create index successfully.");
} catch (IOException e) {
LOG.error("Create index failed " ,e);
} finally {
if (admin != null) {
try {
admin.close();
} catch (IOException e) {
LOG.error("Close admin failed " ,e);
}
}
if (iAdmin != null) {
try {
// Close IndexAdmin Object
iAdmin.close();
} catch (IOException e) {
LOG.error("Close admin failed " ,e);
}
}
}
LOG.info("Exiting createIndex.");
}
样例:如果用户表在创建时对列或列族设置了加密,那么在创建对应的索引表时,需添加对应的加密参数。请参考“管理员指南 > 安全管理 > 安全加固 > 加密HFile和WAL内容”进行安全加固。
//Specify the encryption type of indexed column
HTableDescriptor htd = admin.getTableDescriptor(Bytes.toBytes("user"));
admin.disableTable(tableName);
htd = admin.getTableDescriptor(Bytes.toBytes("user"));
//Instantiate index column description.
HColumnDescriptor indexColDesc = new HColumnDescriptor(IndexMasterObserver.DEFAULT_INDEX_COL_DESC);
indexColDesc.setEncryptionType("AES");
//Set the description of index as the HTable description.
htd.setValue(Constants.INDEX_COL_DESC_BYTES, indexColDesc.toByteArray());
admin.modifyTable("user", htd);
admin.enableTable(tableName);
注意事项
注[1]:创建联合索引
HBase支持在多个字段上创建二级索引,例如在列name和age上。但需要注意的是创建联合索引时需要指定每个列的长度。
IndexSpecification iSpecUnite = new IndexSpecification(indexName);
iSpecUnite.addIndexColumn(new HColumnDescriptor("info"), "name", ValueType.String, 10);
iSpecUnite.addIndexColumn(new HColumnDescriptor("info"), "age", ValueType.String, 3);
相关操作
使用命令创建索引表。
您还可以通过TableIndexer工具在已有用户表中创建索引。
说明:
<table\_name>用户表必须存在。
hbase org.apache.hadoop.hbase.index.mapreduce.TableIndexer -Dtablename.to.index=<table_name> -Dtable.columns.index='IDX1=>cf1:[q1->datatype&length];cf2:[q1->datatype&length],[q2->datatype&length],[q3->datatype& lenght]#IDX2=>cf1:[q5->datatype&length]'
“#”用于区分不同的索引,“;”用于区分不同的列族,“,”用于区分不同的列。
tablename.to.index:创建索引的用户表表名。
table.columns.index:创建索引对应的用户表列。
其中命令中各参数的含义如下:
- IDX1:索引名称
- cf1:列族名称。
- q1:列名。
- datatype:数据类型。数据类型仅支持Int、String、Double、Float类型。
- length:值的最大长度。
获取索引创建时间
当在用户表中添加新的索引时,新索引的创建时间会作为HBase的表格属性被保存在用户表中。这个表格属性包含属性关键字,比如带“_idx”后缀的索引名,创建时间的单位为毫秒。
例如:
如果一个名为“IndexName”的索引被添加进用户表“UserTable”,这个“UserTable”表格将会有下列的属性被添加进这个表格,描述如下。
hbase(main):084:0> desc 'UserTable'
UserTable, {TABLE_ATTRIBUTES => {METADATA => {'IndexName_idx' => '1461303606018', 'INDEX_SPEC' => '\x00\x00\x00\x01\x02I1\x00\x00\x00\x01\x02f1\x02c1\x06Strin
g\x00\x00\x00\x14\x00\x04NONE\x00\x00\x00\x01\x00\x00\x00\x00\x7F\xFF\xFF\xFF'}}
COLUMN FAMILIES DESCRIPTION
{NAME => 'f1', DATA_BLOCK_ENCODING => 'NONE', BLOOMFILTER => 'ROW', REPLICATION_SCOPE => '1', COMPRESSION => 'NONE', VERSIONS => '1', TTL => 'FO
REVER', MIN_VERSIONS => '0', KEEP_DELETED_CELLS => 'FALSE', BLOCKSIZE => '65536', IN_MEMORY => 'false', BLOCKCACHE => 'true'}
1 row(s) in 0.5780 seconds
其中,“IndexName_idx”即为属性关键字,包含了带后缀“_idx”的新增索引“IndexName”。
索引创建时间也可以通过使用HBase标准API接口获取。获取目录创建时间对其他工具开发者来说是非常有用的,例如基于时间范围的备份和存储。