すべてのプロダクト
Search
ドキュメントセンター

Tablestore:ルーティングフィールドの使い方

最終更新日:Dec 28, 2024

検索インデックスを作成する際に、1 つ以上のプライマリキー列をルーティングフィールドとして指定できます。インデックスデータが検索インデックスに書き込まれると、Tablestore はルーティングフィールドの値に基づいてインデックスデータが分散される場所を決定します。ルーティングフィールドの値が同じ行は、同じパーティションにインデックス化されます。

手順

  1. 検索インデックスを作成する際に、1 つ以上のルーティングフィールドを指定します。

    検索インデックスの作成時にルーティングフィールドを指定すると、データの読み取りおよび書き込み操作のために、ルーティングフィールドを使用してインデックスデータが特定されます。

    検索インデックスのスキーマを動的に変更して、検索インデックスのルーティングフィールドを動的に変更できます。たとえば、検索インデックスのスキーマを動的に変更して、デフォルトのルーティングフィールドをカスタムルーティングフィールドに変更したり、カスタムルーティングフィールドをデフォルトのルーティングフィールドに変更したりできます。デフォルトのルーティングフィールドはパーティションキーです。詳細については、検索インデックスのスキーマを動的に変更するを参照してください。

    重要

    Tablestore のプライマリキー列のみをルーティングフィールドとして指定できます。

  2. 検索インデックスを使用してデータをクエリする場合は、クエリリクエストにルーティングフィールドを指定します。

    Tablestore は、クエリリクエストで指定したルーティングフィールドに基づいて、指定されたパーティションのみをスキャンします。これにより、Tablestore によってスキャンされるパーティションが絞り込まれるため、クエリのレイテンシが短縮されます。検索インデックスにルーティングフィールドを指定した場合は、検索インデックスを使用してデータをクエリする際に、ルーティングフィールドを指定する必要があります。検索インデックスにルーティングフィールドを指定するかどうかは、検索インデックスを使用してデータをクエリする際のクエリ結果には影響しません。ただし、ルーティングフィールドを指定しないと、Tablestore は無関係なパーティションをスキャンします。これはシステムリソースを浪費し、クエリのレイテンシを増加させます。

    重要

    ルーティングフィールドには、1 つ以上の値を指定できます。ただし、ルーティングフィールドの値の範囲を指定することはできません。

方法

Tablestore コンソールでルーティングフィールドを指定するか、Tablestore CLI または Tablestore SDK を使用できます。検索インデックスの作成時、または既存の検索インデックスのルーティングフィールドの変更時に、ルーティングフィールドを指定できます。このセクションでは、検索インデックスの作成時にルーティングフィールドを指定する方法の例を示します。検索インデックスのルーティングフィールドを指定する前に満たす必要がある前提条件を以下に示します。

説明

検索インデックスを作成した後、検索インデックスのスキーマを変更して、検索インデックスのルーティングフィールドを変更できます。詳細については、検索インデックスのスキーマを動的に変更するを参照してください。

  • 最大バージョンが 1 に設定されているデータテーブルが作成されます。データテーブルの有効期限 (TTL) は、次のいずれかの条件を満たしています。詳細については、データテーブルの操作を参照してください。

    • データテーブルの TTL が -1 に設定されています。これは、データテーブル内のデータが期限切れにならないことを指定します。

    • データテーブルの TTL が -1 以外の値に設定されており、データテーブルの更新操作は禁止されています。

  • Tablestore SDK を使用してルーティングフィールドを指定する場合は、OTSClient インスタンスが初期化されます。詳細については、OTSClient インスタンスを初期化するを参照してください。

  • Tablestore CLI を使用してルーティングフィールドを指定する場合は、Tablestore CLI がインストールされて起動され、アクセスするインスタンスに関する情報が構成されています。詳細については、Tablestore CLI をダウンロードするおよびTablestore CLI を起動し、アクセス情報を構成するを参照してください。

Tablestore コンソールの使用

Tablestore コンソールで検索インデックスを作成する場合は、詳細設定をオンにして、次の図に示すようにルーティングフィールドを指定します。詳細については、手順 1: 検索インデックスを作成するを参照してください。

image

Tablestore CLI の使用

Tablestore CLI を使用して create_search_index コマンドを実行し、検索インデックスを作成できます。詳細については、検索インデックスを参照してください。

  1. 検索インデックスを作成する際に、ルーティングフィールドを指定します。

    次のサンプルコードは、mysearchindex という名前の検索インデックスを作成する方法の例を示しています。検索インデックスには、LONG 型の gid フィールド、LONG 型の uid フィールド、LONG 型の col2 フィールド、TEXT 型の col3 フィールド、KEYWORD 型の col1 フィールド、および LONG 型の col3V フィールドが含まれています。 col3V フィールドは、データテーブルの col3 列に対応する仮想列です。この例では、検索インデックスのルーティングフィールドは uid フィールドです。

    create_search_index -n mysearchindex

    画面の指示に従って、検索インデックスのスキーマを指定します。検索インデックスを使用してデータをクエリする前に、ビジネス要件に基づいてサンプルコードのフィールド設定を変更する必要があります。サンプルコード:

    {
    
        "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

    画面の指示に従って、クエリ条件を指定します。検索インデックスを使用してデータをクエリする前に、ビジネス要件に基づいてサンプルコードのクエリ条件を変更する必要があります。サンプルコード:

    説明

    この例では、範囲クエリメソッドが使用されています。検索インデックス機能でサポートされているクエリメソッドについては、基本機能を参照してください。

    {
        "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
             }
         }
    }

Tablestore SDK の使用

次の Tablestore SDK を使用して、検索インデックスの作成時にルーティングフィールドを指定できます。Tablestore SDK for JavaTablestore SDK for GoTablestore SDK for PythonTablestore SDK for Node.jsTablestore SDK for .NETTablestore SDK for PHP。この例では、Tablestore SDK for Java を使用して、ルーティングフィールドを指定および使用する方法について説明します。

次のサンプルコードは、order という名前のデータテーブルを作成し、検索インデックスを作成するときにルーティングフィールドを user_id フィールドに設定し、データテーブルにデータを書き込み、クエリリクエストでルーティングフィールドを指定する方法の例を示しています。この例では、データテーブルには STRING 型の order_id 列と STRING 型の user_id 列が含まれています。検索インデックスには、KEYWORD 型の product_name フィールド、LONG 型の order_time フィールド、および 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());

  }