使用二级索引读取数据

更新时间:
复制 MD 格式

使用 Java SDK 通过全局二级索引或本地二级索引读取数据。

前提条件

功能说明

二级索引通过重新组合数据表的主键列和预定义列,提供不同于数据表主键的读取路径。索引表只能用于读取数据。索引表中包含索引主键、系统自动补充的数据表主键,以及创建索引时指定的属性列;如需获取索引表中未包含的属性列,需根据返回的数据表主键反查数据表。关于二级索引的更多信息,请参见二级索引

读取索引表时,主键列的名称和顺序必须与索引表的主键结构一致。例如,数据表以 user_idorder_id 为主键,二级索引使用 category 作为新增索引列时,两类索引表的完整主键顺序如下。

索引类型

创建索引时指定的索引主键

索引表的完整主键顺序

全局二级索引

category

categoryuser_idorder_id。系统将未指定的数据表主键补充到索引主键末尾。

本地二级索引

user_idcategory

user_idcategoryorder_id。第一列索引主键必须与数据表的第一列主键相同。

重要

创建全局二级索引并同步存量数据时,在存量数据构造和同步完成前不能读取索引表。请等待存量数据同步完成后再读取。

调用 getRow 根据完整的索引表主键读取单行数据。

public GetRowResponse getRow(GetRowRequest getRowRequest)
        throws TableStoreException, ClientException

调用 getRange 按索引表主键范围读取数据。

public GetRangeResponse getRange(GetRangeRequest getRangeRequest)
        throws TableStoreException, ClientException

以下示例根据完整主键从全局二级索引 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());

参数说明

单行读取参数

GetRowRequest 包含以下参数。

名称

类型

说明

rowQueryCriteria(必选)

SingleRowQueryCriteria

单行读取条件。

单行读取条件

rowQueryCriteria 的类型为 SingleRowQueryCriteria,包含以下参数。

名称

类型

说明

tableName(必选)

String

索引表名称。

primaryKey(必选)

PrimaryKey

待读取行的完整索引表主键。必须包含创建索引时指定的索引主键和系统自动补充的数据表主键,主键列的名称和顺序必须与索引表定义一致。

columnsToGet(可选)

Set<String>

需要返回的属性列名称,最多指定 128 列。不设置时返回索引表中该行的全部属性列。索引表中未包含的属性列不会返回,需反查数据表获取。

maxVersions(条件必选)

int

每个属性列最多返回的版本数,必须大于 0。二级索引仅保留最新版本,通常设置为 1。与 timeRange 至少设置一个,且不能同时设置。

timeRange(条件必选)

TimeRange

属性列版本的时间戳范围,单位为毫秒,范围为前闭后开区间。与 maxVersions 至少设置一个,且不能同时设置。

filter(可选)

Filter

服务端过滤条件。条件不匹配时不返回该行。

startColumn(可选)

String

返回属性列的起始列名,按列名字典序排序,结果包含该列。主要用于宽行读取。

endColumn(可选)

String

返回属性列的结束列名,按列名字典序排序,结果不包含该列。主要用于宽行读取。

范围读取参数

GetRangeRequest 包含以下参数。

名称

类型

说明

rangeRowQueryCriteria(必选)

RangeRowQueryCriteria

范围读取条件。

范围读取条件

rangeRowQueryCriteria 的类型为 RangeRowQueryCriteria,包含以下参数。

名称

类型

说明

tableName(必选)

String

索引表名称。

inclusiveStartPrimaryKey(必选)

PrimaryKey

读取范围的起始主键,结果包含该主键。必须包含索引表的全部主键列。可使用 INF_MININF_MAX 表示某一主键列的最小值和最大值。

exclusiveEndPrimaryKey(必选)

PrimaryKey

读取范围的结束主键,结果不包含该主键。必须包含索引表的全部主键列。可使用 INF_MININF_MAX 表示某一主键列的最小值和最大值。

direction(可选)

Direction

读取方向。取值为 FORWARDBACKWARD,默认值为 FORWARD。正序读取时起始主键必须小于结束主键;逆序读取时起始主键必须大于结束主键。

limit(可选)

int

单次请求最多返回的行数,必须大于 0。默认值为 -1,表示不由客户端限制返回行数;服务端单次最多返回 5000 行且数据大小不超过 4 MB。

columnsToGet(可选)

Set<String>

需要返回的属性列名称,最多指定 128 列。不设置时返回索引表中各行的全部属性列。如果某行中指定的属性列均不存在,则不返回该行;需要反查数据表时,应先读取索引表中实际存在的列或不设置此参数。

maxVersions(条件必选)

int

每个属性列最多返回的版本数,必须大于 0。二级索引仅保留最新版本,通常设置为 1。与 timeRange 至少设置一个,且不能同时设置。

timeRange(条件必选)

TimeRange

属性列版本的时间戳范围,单位为毫秒,范围为前闭后开区间。与 maxVersions 至少设置一个,且不能同时设置。

filter(可选)

Filter

服务端过滤条件,只返回满足条件的行。

startColumn(可选)

String

返回属性列的起始列名,按列名字典序排序,结果包含该列。主要用于宽行读取。

endColumn(可选)

String

返回属性列的结束列名,按列名字典序排序,结果不包含该列。主要用于宽行读取。

返回值

单行读取返回值

GetRowResponse 包含以下返回参数。

名称

类型

说明

row

Row

返回的行数据。待读取行不存在时返回 null

consumedCapacity

ConsumedCapacity

本次操作消耗的服务能力单元。

范围读取返回值

GetRangeResponse 包含以下返回参数。

名称

类型

说明

rows

List<Row>

本次请求返回的行数据。

nextStartPrimaryKey

PrimaryKey

下一次读取的起始主键。返回值不为 null 时,将其作为下一次请求的 inclusiveStartPrimaryKey 继续读取;返回 null 时表示已读取完指定范围。即使未设置 limit,达到单次响应限制时仍会返回该参数。

consumedCapacity

ConsumedCapacity

本次操作消耗的服务能力单元。

场景示例

按全局二级索引范围读取数据

以下示例从全局二级索引 example_global_index 读取 categorybooks 的数据,并处理分页返回的 nextStartPrimaryKey

PrimaryKey startPrimaryKey = PrimaryKeyBuilder.createPrimaryKeyBuilder()
        .addPrimaryKeyColumn("category", PrimaryKeyValue.fromString("books"))
        .addPrimaryKeyColumn("user_id", PrimaryKeyValue.INF_MIN)
        .addPrimaryKeyColumn("order_id", PrimaryKeyValue.INF_MIN)
        .build();
PrimaryKey endPrimaryKey = PrimaryKeyBuilder.createPrimaryKeyBuilder()
        .addPrimaryKeyColumn("category", PrimaryKeyValue.fromString("books"))
        .addPrimaryKeyColumn("user_id", PrimaryKeyValue.INF_MAX)
        .addPrimaryKeyColumn("order_id", PrimaryKeyValue.INF_MAX)
        .build();

RangeRowQueryCriteria rangeCriteria =
        new RangeRowQueryCriteria("example_global_index");
rangeCriteria.setInclusiveStartPrimaryKey(startPrimaryKey);
rangeCriteria.setExclusiveEndPrimaryKey(endPrimaryKey);
rangeCriteria.setMaxVersions(1);
rangeCriteria.setLimit(100);

List<Row> rows = new ArrayList<>();
while (true) {
    GetRangeResponse response =
            client.getRange(new GetRangeRequest(rangeCriteria));
    rows.addAll(response.getRows());

    if (response.getNextStartPrimaryKey() == null) {
        break;
    }
    rangeCriteria.setInclusiveStartPrimaryKey(
            response.getNextStartPrimaryKey());
}
rows.forEach(System.out::println);

反查数据表获取属性列

以下示例沿用上一示例返回的 rows,从索引表主键中提取数据表主键,并反查数据表 example_table 获取索引表中未包含的 detail 属性列。

for (Row indexRow : rows) {
    PrimaryKey indexPrimaryKey = indexRow.getPrimaryKey();
    PrimaryKey primaryKey = PrimaryKeyBuilder.createPrimaryKeyBuilder()
            .addPrimaryKeyColumn(
                    "user_id",
                    indexPrimaryKey.getPrimaryKeyColumn("user_id").getValue())
            .addPrimaryKeyColumn(
                    "order_id",
                    indexPrimaryKey.getPrimaryKeyColumn("order_id").getValue())
            .build();

    SingleRowQueryCriteria rowCriteria =
            new SingleRowQueryCriteria("example_table", primaryKey);
    rowCriteria.addColumnsToGet("detail");
    rowCriteria.setMaxVersions(1);

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