セカンダリインデックスは、さまざまなシナリオでクエリ効率を向上させます。指定したカラムにインデックスを作成できます。作成されたインデックステーブル内のデータは、これらのインデックスカラムによってソートされます。プライマリテーブルにデータを書き込むと、データは自動的にインデックステーブルに同期され、インデックステーブルへのクエリによってデータを迅速に取得できます。
シナリオ例
通話記録をクエリするシナリオでは、各通話に関する情報が通話終了後にデータテーブルに保存されます。
データテーブルのプライマリキーと事前定義列は次のとおりです:
-
CellNumber と StartTime がプライマリキーです。これらはそれぞれ、発信者番号と通話開始時刻を表します。
-
CalledNumber、Duration、BaseStationNumber が事前定義列です。これらはそれぞれ、着信者番号、通話時間、基地局番号を表します。
次の表は、データテーブルのサンプルデータを示しています。Tablestore のワイドテーブルモデルは、すべての行をプライマリキーでソートし、データを読み取るためのシーケンシャルスキャン (GetRange) 操作を提供します。
|
CellNumber |
StartTime (UNIX タイムスタンプ) |
CalledNumber |
Duration |
BaseStationNumber |
|
123456 |
1532574644 |
654321 |
60 |
1 |
|
234567 |
1532574714 |
765432 |
10 |
1 |
|
234567 |
1532574734 |
123456 |
20 |
3 |
|
345678 |
1532574795 |
123456 |
5 |
2 |
|
345678 |
1532574861 |
123456 |
100 |
2 |
|
456789 |
1532584054 |
345678 |
200 |
3 |
次に挙げるクエリ要件を考えます。必要に応じて、主テーブル、グローバルセカンダリインデックス、またはローカルセカンダリインデックスから必要なデータを取得できます。
-
番号 234567 のすべての発信通話記録をクエリする。
-
番号 123456 へのすべての着信通話記録をクエリする。
-
タイムスタンプ 1532574740 以降に開始された、基地局 2 からのすべての通話記録をクエリする。
-
基地局 3 で、タイムスタンプ 1532574861 から 1532584054 の間に発生したすべての通話の通話時間をクエリする。
-
基地局 3 で、タイムスタンプ 1532574861 から 1532584054 の間に発生したすべての通話について、通話時間の合計、平均、最大値、最小値をクエリする。
-
発信者番号 456789 から着信者番号 345678 へのすべての通話記録をクエリする。
データクエリ
要件に応じて適切なクエリ メソッドを選択してください。
実装方法
次の表に、各クエリ要件の実装方法を示します。
-
テーブルとセカンダリインデックスの作成例については、「付録:データテーブルとセカンダリインデックスの作成例」をご参照ください。
プライマリテーブルを作成した後、サンプルデータを書き込みます。データは自動的にインデックステーブルに同期されます。データの書き込み方法の詳細については、「データの書き込み」をご参照ください。
-
システムは自動的にプライマリキー補完を実行します。これにより、プライマリテーブルのプライマリキー列がインデックス列に追加され、インデックステーブルのプライマリキーが形成されます。
-
ローカルセカンダリインデックスの最初のプライマリキー列は、プライマリテーブルの最初のプライマリキー列と同じである必要があります。
|
クエリ要件 |
実装方法 |
|
番号 234567 のすべての発信通話記録をクエリする。 |
getRange API を呼び出して、データテーブルをスキャンします。 |
|
番号 123456 のすべての着信通話記録をクエリする。 |
CalledNumber 列にインデックスを作成します。次に、getRange API を呼び出して、インデックステーブルをスキャンします。 |
|
タイムスタンプ 1532574740 以降に開始された、基地局 002 からのすべての通話記録をクエリする。 |
BaseStationNumber 列と StartTime 列に複合インデックスを作成します。次に、getRange API を呼び出して、インデックステーブル (グローバルセカンダリインデックス) をスキャンします。 |
|
タイムスタンプ 1532574861 と 1532584054 の間に基地局 003 で発生したすべての通話の通話時間をクエリする。 |
BaseStationNumber 列と StartTime 列に複合インデックスを作成し、Duration 列を属性列としてインデックスに含めます。次に、getRange API を呼び出して、インデックステーブル (グローバルセカンダリインデックス) をスキャンします。 タイムスタンプ 1532574861 と 1532584054 の間に基地局 003 で発生したすべての通話の合計、平均、最大、最小の通話時間をクエリするには、同じ実装方法を使用します。次に、返された各通話時間から最終結果を計算します。 説明
Tablestore SQL クエリを使用することもできます。この方法では、クライアントで計算を実行する必要はありません。SQL ステートメントを使用して、最終的な統計結果を直接取得できます。詳細については、「データのクエリ」をご参照ください。 |
|
発信者番号 456789 から着信者番号 345678 へのすべての通話記録をクエリする。 |
発信者番号に対応する CellNumber 列と、着信者番号に対応する CalledNumber 列に複合インデックスを作成します。Duration 列と BaseStationNumber 列を属性列としてインデックステーブルに含めます。次に、getRange API を呼び出して、インデックステーブル (ローカルセカンダリインデックス) をスキャンします。 |
番号 234567 のすべての発信通話記録のクエリ
番号 123456 のすべての着信通話記録のクエリ
タイムスタンプ 1532574740 以降に開始された、基地局 002 からのすべての通話記録のクエリ
タイムスタンプ 1532574861 と 1532584054 の間に基地局 003 で発生したすべての通話の期間のクエリ
発信者番号 456789 から着信者番号 345678 へのすべての通話記録の照会
付録:データテーブルとセカンダリインデックスの作成例
次の例では、本トピックで使用するプライマリテーブルと、ローカルセカンダリインデックスおよびグローバルセカンダリインデックスを含むセカンダリインデックスの作成方法を示します。
private static final String TABLE_NAME = "CallRecordTable";
private static final String INDEX0_NAME = "IndexOnBeCalledNumber";
private static final String INDEX1_NAME = "IndexOnBaseStation1";
private static final String INDEX2_NAME = "IndexOnBaseStation2";
private static final String INDEX3_NAME = "LocalIndexOnBeCalledNumber";
private static final String PRIMARY_KEY_NAME_1 = "CellNumber";
private static final String PRIMARY_KEY_NAME_2 = "StartTime";
private static final String DEFINED_COL_NAME_1 = "CalledNumber";
private static final String DEFINED_COL_NAME_2 = "Duration";
private static final String DEFINED_COL_NAME_3 = "BaseStationNumber";
private static void createTable(SyncClient client) {
TableMeta tableMeta = new TableMeta(TABLE_NAME);
tableMeta.addPrimaryKeyColumn(new PrimaryKeySchema(PRIMARY_KEY_NAME_1, PrimaryKeyType.INTEGER));
tableMeta.addPrimaryKeyColumn(new PrimaryKeySchema(PRIMARY_KEY_NAME_2, PrimaryKeyType.INTEGER));
tableMeta.addDefinedColumn(new DefinedColumnSchema(DEFINED_COL_NAME_1, DefinedColumnType.INTEGER));
tableMeta.addDefinedColumn(new DefinedColumnSchema(DEFINED_COL_NAME_2, DefinedColumnType.INTEGER));
tableMeta.addDefinedColumn(new DefinedColumnSchema(DEFINED_COL_NAME_3, DefinedColumnType.INTEGER));
// データの有効期間 (TTL) (秒)。値が -1 の場合、データは期限切れになりません。インデックステーブルを持つプライマリテーブルの TTL は -1 にする必要があります。
int timeToLive = -1;
// 保存する最大バージョン数。インデックステーブルを持つプライマリテーブルの最大バージョン数は 1 にする必要があります。
int maxVersions = 1;
TableOptions tableOptions = new TableOptions(timeToLive, maxVersions);
ArrayList<IndexMeta> indexMetas = new ArrayList<IndexMeta>();
IndexMeta indexMeta0 = new IndexMeta(INDEX0_NAME);
indexMeta0.addPrimaryKeyColumn(DEFINED_COL_NAME_1);
indexMetas.add(indexMeta0);
IndexMeta indexMeta1 = new IndexMeta(INDEX1_NAME);
indexMeta1.addPrimaryKeyColumn(DEFINED_COL_NAME_3);
indexMeta1.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2);
indexMetas.add(indexMeta1);
IndexMeta indexMeta2 = new IndexMeta(INDEX2_NAME);
indexMeta2.addPrimaryKeyColumn(DEFINED_COL_NAME_3);
indexMeta2.addPrimaryKeyColumn(PRIMARY_KEY_NAME_2);
indexMeta2.addDefinedColumn(DEFINED_COL_NAME_2);
indexMetas.add(indexMeta2);
IndexMeta indexMeta3 = new IndexMeta(INDEX3_NAME);
indexMeta3.addPrimaryKeyColumn(PRIMARY_KEY_NAME_1);
indexMeta3.addPrimaryKeyColumn(DEFINED_COL_NAME_1);
indexMeta3.addDefinedColumn(DEFINED_COL_NAME_2);
indexMeta3.addDefinedColumn(DEFINED_COL_NAME_3);
// インデックス同期モードを設定します。
indexMeta3.setIndexUpdateMode(IUM_SYNC_INDEX);
// インデックスタイプを IT_LOCAL_INDEX (ローカルセカンダリインデックス) に設定します。
indexMeta3.setIndexType(IT_LOCAL_INDEX);
indexMetas.add(indexMeta3);
CreateTableRequest request = new CreateTableRequest(tableMeta, tableOptions, indexMetas);
client.createTable(request);
}