通过SDK使用二级索引

更新时间:
复制 MD 格式

二级索引相当于把数据表的主键查询能力扩展到了不同的列,当需要使用属性查询数据时,您可以通过创建二级索引加快数据查询的效率。设置预定义列后,在创建二级索引时将预定义列作为索引表的索引列或者属性列。创建二级索引后,您可以使用二级索引进行数据查询。

前提条件

已创建数据表,且数据表的最大版本数(max Versions)必须为1,数据生命周期(Time to Live)必须满足如下条件中的任意一个。

  • 数据表的数据生命周期为-1(数据永不过期)。

  • 数据表的数据生命周期不为-1时,数据表处于禁止更新状态(即是否允许更新为否)。

说明

二级索引的数据生命周期与数据表的数据生命周期相同。

步骤一:(可选)管理预定义列

使用二级索引时,如果未设置预定义列或者已有预定义列不满足需求,您可以为数据表添加或者删除预定义列。您可以使用Java SDK或者Go SDK管理预定义列,此处以Java SDK为例介绍预定义列的使用。

添加预定义列

以下示例向 example_table 添加名为 name 的 STRING 类型预定义列。

AddDefinedColumnRequest request = new AddDefinedColumnRequest();
request.setTableName("example_table");
request.addDefinedColumn("name", DefinedColumnType.STRING);
client.addDefinedColumn(request);

删除预定义列

删除数据表上不需要的预定义列。

以下示例从 example_table 中删除名为 name 的预定义列。

DeleteDefinedColumnRequest request = new DeleteDefinedColumnRequest();
request.setTableName("example_table");
request.addDefinedColumn("name");
client.deleteDefinedColumn(request);

步骤二:创建二级索引

使用CreateIndex接口在已存在的数据表上创建一个索引表用于加速数据查询。二级索引包括全局二级索引和本地二级索引,请根据实际创建。

说明

您也可以使用CreateTable接口在创建数据表的同时创建一个或者多个索引表。具体操作,请参见创建数据表。

您可以通过Java SDK、Go SDK、Python SDK、Node.js SDK、.NET SDK和PHP SDK创建二级索引,此处以Java SDK为例介绍二级索引的创建。

创建全局二级索引

以下示例为 example_table 创建全局二级索引 example_global_index。索引表包含存量数据。

IndexMeta indexMeta = new IndexMeta("example_global_index");
indexMeta.addPrimaryKeyColumn("category");
indexMeta.addDefinedColumn("status");

CreateIndexRequest request =
        new CreateIndexRequest("example_table", indexMeta, true);
client.createIndex(request);

创建本地二级索引

创建本地二级索引时,将数据表的第一列主键作为第一列索引主键,并将索引类型和更新模式分别设置为 IT_LOCAL_INDEX 和 IUM_SYNC_INDEX。

IndexMeta indexMeta = new IndexMeta("example_local_index");
indexMeta.addPrimaryKeyColumn("user_id");
indexMeta.addPrimaryKeyColumn("category");
indexMeta.addDefinedColumn("status");
indexMeta.setIndexType(IndexType.IT_LOCAL_INDEX);
indexMeta.setIndexUpdateMode(IndexUpdateMode.IUM_SYNC_INDEX);

CreateIndexRequest request =
        new CreateIndexRequest("example_table", indexMeta, true);
client.createIndex(request);

步骤三:读取索引表中数据

从索引表中单行或者范围读取数据,当返回的属性列在索引表中时,您可以直接读取索引表获取数据,否则请自行反查数据表获取数据。

您可以通过Java SDK、Go SDK、Python SDK、Node.js SDK、.NET SDK和PHP SDK读取二级索引表中的数据,此处以Java SDK为例介绍二级索引的数据读取。

单行读取数据

读取一行数据。

以下示例根据完整主键从全局二级索引 example_global_index 读取一行数据,并仅返回 status 属性列。

PrimaryKey primaryKey = PrimaryKeyBuilder.createPrimaryKeyBuilder()
        .addPrimaryKeyColumn("category", PrimaryKeyValue.fromString("books"))
        .addPrimaryKeyColumn("user_id", PrimaryKeyValue.fromString("user-1"))
        .addPrimaryKeyColumn("order_id", PrimaryKeyValue.fromLong(101L))
        .build();

SingleRowQueryCriteria criteria =
        new SingleRowQueryCriteria("example_global_index", primaryKey);
criteria.addColumnsToGet("status");
criteria.setMaxVersions(1);

GetRowResponse response = client.getRow(new GetRowRequest(criteria));
System.out.println(response.getRow());

范围读取数据

读取指定主键范围内的数据。

使用全局二级索引

当需要返回的属性列在索引表中时,可以直接读取索引表获取数据。

private static void scanFromIndex(SyncClient client) {
    //设置索引表名称。
    RangeRowQueryCriteria rangeRowQueryCriteria = new RangeRowQueryCriteria("<INDEX_NAME>");

    //设置起始主键。
    PrimaryKeyBuilder startPrimaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    //设置需要读取的索引列最小值。
    startPrimaryKeyBuilder.addPrimaryKeyColumn(DEFINED_COL_NAME_1, PrimaryKeyValue.INF_MIN);
    //设置数据表主键最小值。
    startPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, PrimaryKeyValue.INF_MIN);
    //设置数据表主键最小值。
    startPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, PrimaryKeyValue.INF_MIN);
    rangeRowQueryCriteria.setInclusiveStartPrimaryKey(startPrimaryKeyBuilder.build());

    //设置结束主键。
    PrimaryKeyBuilder endPrimaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    //设置需要读取的索引列最大值。
    endPrimaryKeyBuilder.addPrimaryKeyColumn(DEFINED_COL_NAME_1, PrimaryKeyValue.INF_MAX);
    //设置数据表主键最大值。
    endPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, PrimaryKeyValue.INF_MAX);
    //设置数据表主键最大值。
    endPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, PrimaryKeyValue.INF_MAX);
    rangeRowQueryCriteria.setExclusiveEndPrimaryKey(endPrimaryKeyBuilder.build());

    rangeRowQueryCriteria.setMaxVersions(1);

    System.out.println("扫描索引表的结果为:");
    while (true) {
        GetRangeResponse getRangeResponse = client.getRange(new GetRangeRequest(rangeRowQueryCriteria));
        for (Row row : getRangeResponse.getRows()) {
            System.out.println(row);
        }

        //如果nextStartPrimaryKey不为null,则继续读取数据。
        if (getRangeResponse.getNextStartPrimaryKey() != null) {
            rangeRowQueryCriteria.setInclusiveStartPrimaryKey(getRangeResponse.getNextStartPrimaryKey());
        } else {
            break;
        }
    }
}

当需要返回的属性列不在索引表中时,请自行反查数据表获取数据。

private static void scanFromIndex(SyncClient client) {
    //设置索引表名称。
    RangeRowQueryCriteria rangeRowQueryCriteria = new RangeRowQueryCriteria("<INDEX_NAME>");

    //设置起始主键。
    PrimaryKeyBuilder startPrimaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    //设置需要读取的索引列最小值。
    startPrimaryKeyBuilder.addPrimaryKeyColumn(DEFINED_COL_NAME_1, PrimaryKeyValue.INF_MIN);
    //设置数据表主键最小值。
    startPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, PrimaryKeyValue.INF_MIN);
    //设置数据表主键最小值。
    startPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, PrimaryKeyValue.INF_MIN);
    rangeRowQueryCriteria.setInclusiveStartPrimaryKey(startPrimaryKeyBuilder.build());

    //设置结束主键。
    PrimaryKeyBuilder endPrimaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    //设置需要读取的索引列最大值。
    endPrimaryKeyBuilder.addPrimaryKeyColumn(DEFINED_COL_NAME_1, PrimaryKeyValue.INF_MAX);
    //设置数据表主键最大值。
    endPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, PrimaryKeyValue.INF_MAX);
    //设置数据表主键最大值。
    endPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, PrimaryKeyValue.INF_MAX);
    rangeRowQueryCriteria.setExclusiveEndPrimaryKey(endPrimaryKeyBuilder.build());

    rangeRowQueryCriteria.setMaxVersions(1);

    while (true) {
        GetRangeResponse getRangeResponse = client.getRange(new GetRangeRequest(rangeRowQueryCriteria));
        for (Row row : getRangeResponse.getRows()) {
            PrimaryKey curIndexPrimaryKey = row.getPrimaryKey();
            PrimaryKeyColumn pk1 = curIndexPrimaryKey.getPrimaryKeyColumn(PRIMARY_KEY_NAME_1);
            PrimaryKeyColumn pk2 = curIndexPrimaryKey.getPrimaryKeyColumn(PRIMARY_KEY_NAME_2);
            PrimaryKeyBuilder mainTablePKBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
            mainTablePKBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, pk1.getValue());
            mainTablePKBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, pk2.getValue());
            //根据索引表主键构造数据表主键。
            PrimaryKey mainTablePK = mainTablePKBuilder.build();

            //反查数据表。
            SingleRowQueryCriteria criteria = new SingleRowQueryCriteria("<TABLE_NAME>", mainTablePK);
            //设置读取数据表的DEFINED_COL_NAME_3列。
            criteria.addColumnsToGet(DEFINED_COL_NAME_3);
            //设置读取最新版本。
            criteria.setMaxVersions(1);
            GetRowResponse getRowResponse = client.getRow(new GetRowRequest(criteria));
            Row mainTableRow = getRowResponse.getRow();
            System.out.println(row);
        }

        //如果nextStartPrimaryKey不为null,则继续读取数据。
        if (getRangeResponse.getNextStartPrimaryKey() != null) {
            rangeRowQueryCriteria.setInclusiveStartPrimaryKey(getRangeResponse.getNextStartPrimaryKey());
        } else {
            break;
        }
    }
}

使用本地二级索引

当需要返回的属性列在索引表中时,可以直接读取索引表获取数据。

private static void scanFromIndex(SyncClient client) {
    //设置索引表名称。
    RangeRowQueryCriteria rangeRowQueryCriteria = new RangeRowQueryCriteria("INDEX_NAME");

    //设置起始主键。
    PrimaryKeyBuilder startPrimaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    //设置需要读取的索引列最小值。
    startPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, PrimaryKeyValue.INF_MIN);
    //设置需要读取的索引列最小值。
    startPrimaryKeyBuilder.addPrimaryKeyColumn(DEFINED_COL_NAME_1, PrimaryKeyValue.INF_MIN);
    //设置数据表主键最小值。
    startPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, PrimaryKeyValue.INF_MIN);
    rangeRowQueryCriteria.setInclusiveStartPrimaryKey(startPrimaryKeyBuilder.build());

    //设置结束主键。
    PrimaryKeyBuilder endPrimaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    //设置需要读取的索引列最大值。
    endPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, PrimaryKeyValue.INF_MAX);
    //设置需要读取的索引列最大值。
    endPrimaryKeyBuilder.addPrimaryKeyColumn(DEFINED_COL_NAME_1, PrimaryKeyValue.INF_MAX);
    //设置数据表主键最大值。
    endPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, PrimaryKeyValue.INF_MAX);
    rangeRowQueryCriteria.setExclusiveEndPrimaryKey(endPrimaryKeyBuilder.build());

    rangeRowQueryCriteria.setMaxVersions(1);

    System.out.println("扫描索引表的结果为:");
    while (true) {
        GetRangeResponse getRangeResponse = client.getRange(new GetRangeRequest(rangeRowQueryCriteria));
        for (Row row : getRangeResponse.getRows()) {
            System.out.println(row);
        }

        //如果nextStartPrimaryKey不为null, 则继续读取。
        if (getRangeResponse.getNextStartPrimaryKey() != null) {
            rangeRowQueryCriteria.setInclusiveStartPrimaryKey(getRangeResponse.getNextStartPrimaryKey());
        } else {
            break;
        }
    }
}

当需要返回的属性列不在索引表中时,请自行反查数据表获取数据。

private static void scanFromIndex(SyncClient client) {
    //设置索引表名称。
    RangeRowQueryCriteria rangeRowQueryCriteria = new RangeRowQueryCriteria("<INDEX_NAME>");

    //设置起始主键。
    PrimaryKeyBuilder startPrimaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    //设置需要读取的索引列最小值。
    startPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, PrimaryKeyValue.INF_MIN);
    //设置需要读取的索引列最小值。
    startPrimaryKeyBuilder.addPrimaryKeyColumn(DEFINED_COL_NAME_1, PrimaryKeyValue.INF_MIN);
    //设置数据表主键最小值。
    startPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, PrimaryKeyValue.INF_MIN);
    rangeRowQueryCriteria.setInclusiveStartPrimaryKey(startPrimaryKeyBuilder.build());

    //设置结束主键。
    PrimaryKeyBuilder endPrimaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    //设置需要读取的索引列最大值。
    endPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, PrimaryKeyValue.INF_MAX);
    //设置需要读取的索引列最大值。
    endPrimaryKeyBuilder.addPrimaryKeyColumn(DEFINED_COL_NAME_1, PrimaryKeyValue.INF_MAX);
    //设置数据表主键最大值。
    endPrimaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, PrimaryKeyValue.INF_MAX);
    rangeRowQueryCriteria.setExclusiveEndPrimaryKey(endPrimaryKeyBuilder.build());

    rangeRowQueryCriteria.setMaxVersions(1);

    while (true) {
        GetRangeResponse getRangeResponse = client.getRange(new GetRangeRequest(rangeRowQueryCriteria));
        for (Row row : getRangeResponse.getRows()) {
            PrimaryKey curIndexPrimaryKey = row.getPrimaryKey();
            PrimaryKeyColumn pk1 = curIndexPrimaryKey.getPrimaryKeyColumn(PRIMARY_KEY_NAME_1);
            PrimaryKeyColumn pk2 = curIndexPrimaryKey.getPrimaryKeyColumn(PRIMARY_KEY_NAME_2);
            PrimaryKeyBuilder mainTablePKBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
            mainTablePKBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, pk1.getValue());
            mainTablePKBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, pk2.getValue());
            //根据索引表主键构造数据表主键。
            PrimaryKey mainTablePK = mainTablePKBuilder.build();

            //反查数据表。
            SingleRowQueryCriteria criteria = new SingleRowQueryCriteria("TABLE_NAME", mainTablePK);
            // 读取主表的DEFINED_COL_NAME3列。
            criteria.addColumnsToGet(DEFINED_COL_NAME3);
            //设置读取最新版本。
            criteria.setMaxVersions(1);
            GetRowResponse getRowResponse = client.getRow(new GetRowRequest(criteria));
            Row mainTableRow = getRowResponse.getRow();
            System.out.println(row);
        }

        //如果nextStartPrimaryKey不为null, 则继续读取。
        if (getRangeResponse.getNextStartPrimaryKey() != null) {
            rangeRowQueryCriteria.setInclusiveStartPrimaryKey(getRangeResponse.getNextStartPrimaryKey());
        } else {
            break;
        }
    }
}

附录:删除索引表

删除不需要的索引表。

您可以通过Java SDK、Go SDK、Python SDK、Node.js SDK、.NET SDK和PHP SDK删除二级索引,此处以Java SDK为例介绍二级索引的删除。

以下示例删除数据表 example_table 中的二级索引 example_index。

DeleteIndexRequest request =
        new DeleteIndexRequest("example_table", "example_index");
DeleteIndexResponse response = client.deleteIndex(request);
System.out.println(response.getRequestId());

常见问题

相关文档