全部產品
Search
文件中心

Tablestore:通過SDK使用二級索引

更新時間:Jun 30, 2024

二級索引相當於把資料表的主鍵查詢能力擴充到了不同的列,當需要使用屬性查詢資料時,您可以通過建立二級索引加快資料查詢的效率。設定預定義列後,在建立二級索引時將預定義列作為索引表的索引列或者屬性列。建立二級索引後,您可以使用二級索引進行資料查詢。

前提條件

已建立資料表,且資料表的最大版本數(max Versions)必須為1,資料生命週期(Time to Live)必須滿足如下條件中的任意一個。

  • 資料表的資料生命週期為-1(資料永不到期)。

  • 資料表的資料生命週期不為-1時,資料表處于禁止更新狀態(即是否允許更新)。

說明

二級索引的資料生命週期與資料表的資料生命週期相同。

步驟一:(可選)管理預定義列

使用二級索引時,如果未設定預定義列或者已有預定義列不滿足需求,您可以為資料表添加或者刪除預定義列。您可以使用Java SDK或者Go SDK管理預定義列,此處以Java SDK為例介紹預定義列的使用。

添加預定義列

以下樣本用於為資料表增加預定義列,預定義列分別為definedColumnName01(String類型)、definedColumnName02(Integer類型)和definedColumnName03(String類型)。

public static void addDefinedColumnRequest(SyncClient client) {
    AddDefinedColumnRequest addDefinedColumnRequest = new AddDefinedColumnRequest();
    //設定資料表名稱。
    addDefinedColumnRequest.setTableName("<TABLE_NAME>");
    //為資料表添加預定義列。
    addDefinedColumnRequest.addDefinedColumn("definedColumnName01",DefinedColumnType.STRING);
    addDefinedColumnRequest.addDefinedColumn("definedColumnName02",DefinedColumnType.INTEGER);
    addDefinedColumnRequest.addDefinedColumn("definedColumnName03",DefinedColumnType.STRING);
    client.addDefinedColumn(addDefinedColumnRequest);
}

刪除預定義列

刪除資料表上不需要的預定義列。

以下樣本用於刪除資料表的預定義列definedColumnName01和definedColumnName02。

public static void deleteDefinedColumnRequest(SyncClient client){
    DeleteDefinedColumnRequest deleteDefinedColumnRequest = new DeleteDefinedColumnRequest();
    //設定資料表名稱。
    deleteDefinedColumnRequest.setTableName("<TABLE_NAME>");
    //添加要刪除的預定義列。
    deleteDefinedColumnRequest.addDefinedColumn("definedColumnName01");
    deleteDefinedColumnRequest.addDefinedColumn("definedColumnName02");
    client.deleteDefinedColumn(deleteDefinedColumnRequest);
}

步驟二:建立二級索引

使用CreateIndex介面在已存在的資料表上建立一個索引表用於加速資料查詢。二級索引包括全域二級索引和本地二級索引,請根據實際建立。

說明

您也可以使用CreateTable介面在建立資料表的同時建立一個或者多個索引表。具體操作,請參見建立資料表

您可以通過Java SDKGo SDKPython SDKNode.js SDK.NET SDKPHP SDK建立二級索引,此處以Java SDK為例介紹二級索引的建立。

建立全域二級索引

以下樣本用於為資料表建立一個全域二級索引。

private static void createIndex(SyncClient client) {
    //設定索引表名稱。
    IndexMeta indexMeta = new IndexMeta("<INDEX_NAME>"); 
    //為索引表添加主鍵列,設定DEFINED_COL_NAME_1列為索引表的第一列主鍵。
    indexMeta.addPrimaryKeyColumn(DEFINED_COL_NAME_1); 
    //為索引表添加主鍵列,設定PRIMARY_KEY_NAME_2列為索引表的第二列主鍵。
    indexMeta.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2); 
    //為索引表添加屬性列,設定DEFINED_COL_NAME_2列為索引表的屬性列。
    indexMeta.addDefinedColumn(DEFINED_COL_NAME_2); 
    //添加索引表到資料表,包含存量資料。
    //CreateIndexRequest request = new CreateIndexRequest("<TABLE_NAME>", indexMeta, true); 
    //添加索引表到資料表,不包含存量資料。
    CreateIndexRequest request = new CreateIndexRequest("<TABLE_NAME>", indexMeta, false); 
    /**通過將IncludeBaseData參數設定為true,建立索引表後會開啟資料表中存量資料的同步,然後可以通過索引表查詢全部資料,
       同步時間和資料量的大小有一定的關係。
    */
    //request.setIncludeBaseData(true);
    //建立索引表。
    client.createIndex(request); 
}

建立本地二級索引

以下樣本用於建立一個本地二級索引。

private static void createIndex(SyncClient client) {
    //設定索引表名稱。
    IndexMeta indexMeta = new IndexMeta("<INDEX_NAME>"); 
    //為索引表添加主鍵列,設定PRIMARY_KEY_NAME_1列為索引表的第一列主鍵。
    //本地二級索引的第一列主鍵必須與資料表的第一列主鍵相同。
    indexMeta.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1); 
    //為索引表添加主鍵列,設定DEFINED_COL_NAME_1列為索引表的第二列主鍵。
    indexMeta.addPrimaryKeyColumn(DEFINED_COL_NAME_1); 
    //為索引表添加屬性列,設定DEFINED_COL_NAME_2列為索引表的屬性列。
    indexMeta.addDefinedColumn(DEFINED_COL_NAME_2); 
    //設定索引類型為IT_LOCAL_INDEX(本地二級索引)。
    indexMeta.setIndexType(IT_LOCAL_INDEX);
    //設定同步模式為IUM_SYNC_INDEX(同步更新)。
    indexMeta.setIndexUpdateMode(IUM_SYNC_INDEX);
    //添加索引表到資料表,包含存量資料。
    //CreateIndexRequest request = new CreateIndexRequest("<TABLE_NAME>", indexMeta, true); 
    //添加索引表到資料表,不包含存量資料。
    CreateIndexRequest request = new CreateIndexRequest("<TABLE_NAME>", indexMeta, false); 
    /**通過將IncludeBaseData參數設定為true,建立索引表後會開啟資料表中存量資料的同步,然後可以通過索引表查詢全部資料,
       同步時間和資料量的大小有一定的關係。
    */
    //request.setIncludeBaseData(true);
    //建立索引表。
    client.createIndex(request); 
}

步驟三:讀取索引表中資料

從索引表中單行或者範圍讀取資料,當返回的屬性列在索引表中時,您可以直接讀取索引表擷取資料,否則請自行反查資料表擷取資料。

您可以通過Java SDKGo SDKPython SDKNode.js SDK.NET SDKPHP SDK讀取二級索引表中的資料,此處以Java SDK為例介紹二級索引的資料讀取。

單行讀取資料

讀取一行資料。

以下樣本用於使用索引表讀取一行資料,設定讀取指定的列。

private static void getRowFromIndex(SyncClient client) {
    //構造主鍵。如果讀取本地二級索引中的資料,索引表的第一列主鍵必須與資料表的第一列主鍵相同。
    PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    primaryKeyBuilder.addPrimaryKeyColumn(DEFINED_COL_NAME_1, PrimaryKeyValue.fromString("def1"));
    primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1, PrimaryKeyValue.fromLong(100));
    primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2, PrimaryKeyValue.fromString("pri1"));
    PrimaryKey primaryKey = primaryKeyBuilder.build();

    //讀取一行資料,設定索引表名稱。
    SingleRowQueryCriteria criteria = new SingleRowQueryCriteria("<INDEX_NAME>", primaryKey);
    //設定讀取最新版本。
    criteria.setMaxVersions(1);
    GetRowResponse getRowResponse = client.getRow(new GetRowRequest(criteria));
    Row row = getRowResponse.getRow();
    //如果讀取的行不存在,則傳回值為null。
    System.out.println("讀取完畢,結果為: ");
    System.out.println(row);

    //設定讀取某些列。
    criteria.addColumnsToGet("Col0");
    getRowResponse = client.getRow(new GetRowRequest(criteria));
    row = getRowResponse.getRow();
    
    System.out.println("讀取完畢,結果為:");
    System.out.println(row);
} 

範圍讀取資料

讀取指定主鍵範圍內的資料。

使用全域二級索引

當需要返回的屬性列在索引表中時,可以直接讀取索引表擷取資料。

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 SDKGo SDKPython SDKNode.js SDK.NET SDKPHP SDK刪除二級索引,此處以Java SDK為例介紹二級索引的刪除。

以下樣本用於刪除指定索引表。

private static void deleteIndex(SyncClient client) {
    //設定資料表名稱和索引表名稱。
    DeleteIndexRequest request = new DeleteIndexRequest("<TABLE_NAME>", "<INDEX_NAME>"); 
    //刪除索引表。
    client.deleteIndex(request); 
}

常見問題

相關文檔