Updated on 2022-09-14 GMT+08:00

Creating a Secondary Index

Function

You can manage HBase secondary indexes using methods provided in org.apache.hadoop.hbase.hindex.client.HIndexAdmin. This class provides methods of creating an index.

Secondary indexes cannot be modified. If you need to modify them, delete old indexes and create new ones.

Example Code

The following code snippet belongs to the createIndex method in the HBaseSample class of the com.huawei.bigdata.hbase.examples package.

public void createIndex() {
    LOG.info("Entering createIndex.");

    String indexName = "index_name";
    // Create hindex instance
    TableIndices tableIndices = new TableIndices();
    IndexSpecification iSpec = new IndexSpecification(indexName);
    iSpec.addIndexColumn(ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("info")).build(),
            "name", ValueType.STRING);// Note[1]
    tableIndices.addIndex(iSpec);

    HIndexAdmin iAdmin = null;
    Admin admin = null;
    try {

      admin = conn.getAdmin();
      iAdmin = HIndexClient.newHIndexAdmin(admin);

      // add index to the table
      iAdmin.addIndices(tableName, tableIndices);

      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.");
  } 
By default, newly created level-2 indexes are disabled. To enable a specified level-2 index, see the following code snippet. The following code snippet belongs to the enableIndex method in the HBaseSample class of the com.huawei.bigdata.hbase.examples packet.
    public void enableIndex() {
        LOG.info("Entering createIndex.");

        // Name of the index to be enabled
        String indexName = "index_name";

        List<String> indexNameList = new ArrayList<String>();
        indexNameList.add(indexName);

        HIndexAdmin iAdmin = null;
        Admin admin = null;
        try {
            admin = conn.getAdmin();
            iAdmin = HIndexClient.newHIndexAdmin(admin);

            // Alternately, enable the specified indices
            iAdmin.enableIndices(tableName, indexNameList);
            LOG.info("Successfully enable indices {}  of the table {}", indexNameList, tableName);
        } catch (IOException e) {
            LOG.error("Failed to enable indices {}  of the table {} . {}", indexNameList, tableName, e);
        } finally {
            if (admin != null) {
                try {
                    admin.close();
                } catch (IOException e) {
                    LOG.error("Close admin failed ", e);
                }
            }
            if (iAdmin != null) {
                try {
                    iAdmin.close();
                } catch (IOException e) {
                    LOG.error("Close admin failed ", e);
                }
            }
        }
    }

Precautions

Create a combination index.

HBase supports creation of secondary indexes on multiple fields, for example, the name and age columns.

HIndexSpecification iSpecUnite = new HIndexSpecification(indexName); 
 iSpecUnite.addIndexColumn(new HColumnDescriptor("info"), "name", ValueType.String, 10); 
 iSpecUnite.addIndexColumn(new HColumnDescriptor("info"), "age", ValueType.String, 3);

Related Operations

Create an index table by running a command.

You can also use the TableIndexer tool to create an index in an existing user table.

The <table_name> user table must exist.

hbase org.apache.hadoop.hbase.hindex.mapreduce.TableIndexer -Dtablename.to.index=<table_name> -Dindexspecs.to.add='IDX1=>cf1:[q1->datatype];cf2:[q1->datatype],[q2->datatype],[q3->datatype]#IDX2=>cf1:[q5->datatype]' -Dindexnames.to.build='IDX1'

A number sign "#" is used to separate indexes. A semicolon ";" is used to separate column families. A comma "," is used to separate columns.

tablename.to.index: indicates the name of the table where the index is created.

indexspecs.to.add: indicates the user table columns corresponding to the index.

The parameters in the command are described as follows:

  • IDX1: indicates the index name.
  • cf1: indicates the column family name.
  • q1: indicates the column name.
  • datatype: indicates the data type. Only the Integer, String, Double, Float, Long, Short, Byte and Char formats are supported.