全部產品
Search
文件中心

Tablestore:多元索引路由欄位的使用

更新時間:Aug 29, 2024

建立多元索引時,您可以選擇部分主鍵列作為路由欄位,在進行索引資料寫入時,Table Store會根據路由欄位的值計算索引資料的分布位置,路由欄位的值相同的記錄會被索引到相同的資料分區中。

使用流程

  1. 建立索引時,指定一個或多個路由欄位。

    您在建立多元索引時指定了路由欄位後,索引資料的讀寫都會使用該路由欄位進行定位。

    多元索引的路由鍵支援動態改變。如果想使用系統預設路由(即主鍵列路由)或者重新指定其他欄位為路由欄位,您可以通過動態修改schema功能實現路由鍵修改。更多資訊,請參見動態修改schema

    重要

    路由欄位只能是Table Store的主鍵列。

  2. 在索引查詢時,在查詢請求中指定路由欄位值。

    查詢資料時使用路由定向搜尋指定資料分區,可以減少長尾對延遲的影響。對於自訂路由的查詢請求,都要求使用者提供路由欄位。如不指定路由鍵,雖然查詢結果一樣,但查詢時會訪問無關的資料分區,浪費系統資源,增加訪問延遲。

    重要

    路由鍵可配置為單值或多值,不支援範圍。

使用方式

您可以使用控制台、命令列工具或者SDK進行路由鍵配置。路由鍵支援在建立多元索引時配置或者在建立多元索引後修改。此處以建立多元索引時配置路由鍵為例介紹。

說明

在建立多元索引後,如需修改多元索引的路由鍵,請通過動態修改schema實現。具體操作,請參見動態修改schema

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

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

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

  • 使用SDK方式進行操作時,還需要完成初始化Client。具體操作,請參見初始化OTSClient

  • 使用命令列工具方式進行操作前,還需要完成下載並啟動命令列工具,然後配置接入執行個體資訊。具體操作,請參見下載命令列工具啟動並配置接入執行個體

使用控制台

Table Store控制台建立多元索引時,開啟進階選項開關並進行路由鍵配置,如下圖所示。具體操作,請參見建立多元索引

image

使用命令列工具

通過命令列工具執行create_search_index命令建立多元索引。更多資訊,請參見多元索引

  1. 建立多元索引時指定路由鍵。

    以下樣本用於建立名稱為mysearchindex的多元索引,該多元索引有gid(long類型)、uid(long類型)、col2(long類型)、col3(text類型)、col1(keyword類型)何col3V(long類型)欄位。其中col3V為虛擬列,對應原始列為col3。多元索引的路由鍵配置為uid。

    create_search_index -n mysearchindex

    根據系統提示輸入索引schema,請根據實際欄位修改樣本後再使用。樣本如下:

    {
    
        "IndexSetting": {
            "RoutingFields": ["uid"]
        },
        "FieldSchemas": [
        {
            "FieldName": "gid",
            "FieldType": "LONG",
            "Index": true,
            "EnableSortAndAgg": true,
            "Store": true,
            "IsArray": false,
            "IsVirtualField": false
        },
        {
            "FieldName": "uid",
            "FieldType": "LONG",
            "Index": true,
            "EnableSortAndAgg": true,
            "Store": true,
            "IsArray": false,
            "IsVirtualField": false
        },
        {
            "FieldName": "col2",
            "FieldType": "LONG",
            "Index": true,
            "EnableSortAndAgg": true,
            "Store": true,
            "IsArray": false,
            "IsVirtualField": false
        },
        {
            "FieldName": "col3",
            "FieldType": "TEXT",
            "Index": true,
            "Analyzer": "single_word",
            "AnalyzerParameter": {
            "CaseSensitive": true,
                "DelimitWord": null
            },
            "EnableSortAndAgg": false,
            "Store": true,
            "IsArray": false,
            "IsVirtualField": false
        },
        {
            "FieldName": "col1",
            "FieldType": "KEYWORD",
            "Index": true,
            "EnableSortAndAgg": true,
            "Store": true,
            "IsArray": false,
            "IsVirtualField": false
        },
        {
            "FieldName": "col3V",
            "FieldType": "LONG",
            "Index": true,
            "EnableSortAndAgg": true,
            "Store": true,
            "IsArray": false,
            "IsVirtualField": true,
            "SourceFieldNames": [
            "col3"
            ]
        }]
    }
  2. 使用多元索引查詢資料時指定路由鍵。

    以下樣本用於使用mysearchindex查詢col2列小於200的行資料。查詢時帶有多元索引路由鍵uid。

    search -n search_index --return_all_indexed

    根據系統提示輸入查詢條件,請根據實際欄位修改樣本後再使用。樣本如下:

    說明

    此處以RangeQuery(範圍查詢)為例介紹,如需使用其他查詢方式,請參見多元索引基礎功能

    {
        "Offset": -1,
        "Limit": 10,
        "Collapse": null,
        "Sort": null,
        "GetTotalCount": true,
        "Token": null,
    	  "IndexSetting": {
            "RoutingFields": ["uid"]
        },
        "Query": {
            "Name": "RangeQuery",
            "Query": {
                "FieldName": "col2",
                "From": null,
                "To": 200,
                "IncludeLower": false,
                "IncludeUpper": false
             }
         }
    }

使用SDK

您可以使用Java SDKGo SDKPython SDKNode.js SDK.NET SDKPHP SDK在建立多元索引時配置路由鍵。此處以Java SDK為例介紹路由鍵的配置和使用。

以下樣本用於建立order資料表時建立order_index多元索引並指定路由欄位為user_id欄位。然後寫入資料並帶上路由欄位進行查詢。該資料表有order_id(string類型)和user_id(string類型);該多元索引有product_name(keyword類型)、order_time(long類型)和user_id(keyword類型)欄位,多元索引的路由鍵為user_id欄位。

private static void testRoute(SyncClient client) throws InterruptedException {
    //建立表。
    TableMeta meta = new TableMeta("order");
    meta.addPrimaryKeyColumn("order_id",PrimaryKeyType.STRING);
    meta.addPrimaryKeyColumn("user_id",PrimaryKeyType.STRING);
    TableOptions options = new TableOptions();
    options.setMaxVersions(1);
    options.setTimeToLive(-1);
    CreateTableRequest request = new CreateTableRequest(meta,options);
    request.setReservedThroughput(new ReservedThroughput(new CapacityUnit(0, 0)));
    CreateTableResponse response = client.createTable(request);

    //建立多元索引並指定路由欄位。
    CreateSearchIndexRequest searchIndexRequest = new CreateSearchIndexRequest();
    //訂單表。
    searchIndexRequest.setTableName("order"); 
    //訂單表索引名。
    searchIndexRequest.setIndexName("order_index"); 
    IndexSchema indexSchema = new IndexSchema();
    IndexSetting indexSetting = new IndexSetting();
    //設定user_id為路由欄位。
    indexSetting.setRoutingFields(Arrays.asList("user_id"));
    indexSchema.setIndexSetting(indexSetting);

    //添加索引欄位。此處只是給出樣本,您可以根據業務需求添加索引欄位。
    indexSchema.setFieldSchemas(Arrays.asList(
        new FieldSchema("product_name",FieldType.KEYWORD).setStore(true).setIndex(true),
        new FieldSchema("order_time",FieldType.LONG).setStore(true).setEnableSortAndAgg(true).setIndex(true),
        new FieldSchema("user_id",FieldType.KEYWORD).setStore(true).setIndex(true)
    ));

    searchIndexRequest.setIndexSchema(indexSchema);
    client.createSearchIndex(searchIndexRequest);
    //等待資料表載入。
    Thread.sleep(6*1000); 

    //插入一些測試資料。

    String[] productName = new String[]{"product a", "product b", "product c"};
    String[] userId = new String[]{"00001", "00002", "00003", "00004", "00005"};
    for (int i = 0; i < 100; i++){

      PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
      primaryKeyBuilder.addPrimaryKeyColumn("order_id",PrimaryKeyValue.fromString(i+""));
      primaryKeyBuilder.addPrimaryKeyColumn("user_id",PrimaryKeyValue.fromString(userId[i%(userId.length)]));
      PrimaryKey primaryKey = primaryKeyBuilder.build();

      RowPutChange rowPutChange = new RowPutChange("order",primaryKey);

      //寫入屬性列。
      rowPutChange.addColumn("product_name",ColumnValue.fromString(productName[i%(productName.length)]));
      rowPutChange.addColumn("order_time",ColumnValue.fromLong(System.currentTimeMillis()));
      rowPutChange.setCondition(new Condition(RowExistenceExpectation.IGNORE));

      client.putRow(new PutRowRequest(rowPutChange));

    }
    //等待資料同步到多元索引。
    Thread.sleep(20*1000);

    //帶上路由欄位的查詢。
    SearchRequest searchRequest = new SearchRequest();
    searchRequest.setTableName("order");
    searchRequest.setIndexName("order_index");
    MatchQuery matchQuery = new MatchQuery();
    matchQuery.setFieldName("user_id");
    matchQuery.setText("00002");
    SearchQuery searchQuery = new SearchQuery();
    searchQuery.setQuery(matchQuery);
    searchQuery.setGetTotalCount(true);

    SearchRequest.ColumnsToGet columnsToGet = new SearchRequest.ColumnsToGet();
    columnsToGet.setReturnAll(true);
    searchRequest.setColumnsToGet(columnsToGet);
    searchRequest.setSearchQuery(searchQuery);

    PrimaryKeyBuilder pkbuild = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    pkbuild.addPrimaryKeyColumn("user_id",PrimaryKeyValue.fromString("00002"));
    PrimaryKey routingValue = pkbuild.build();
    searchRequest.setRoutingValues(Arrays.asList(routingValue));
    SearchResponse searchResponse = client.search(searchRequest);

    System.out.println(searchResponse.isAllSuccess());
    System.out.println("totalCount:"+ searchResponse.getTotalCount());
    System.out.println("RowCount:"+searchResponse.getRows().size());

  }