セカンダリインデックスを使用する - AWS SDK for Java 2.x

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

セカンダリインデックスを使用する

セカンダリインデックスは、クエリやスキャンの操作に使用する代替キーを定義することで、データアクセスを向上させます。グローバルセカンダリインデックス (GSI) には、パーティションキーとソートキーがあり、ベーステーブルのものとは異なる場合があります。対照的に、ローカルセカンダリインデックス (LSI) はプライマリインデックスのパーティションキーを使用します。

セカンダリインデックス注釈でデータクラスに注釈を付けます。

セカンダリインデックスに含まれる属性には、@DynamoDbSecondaryPartitionKey または @DynamoDbSecondarySortKey 注釈が必要です。

次のクラスは 2 つのインデックスの注釈を表示します。GSI という名前の SubjectLastPostedDateIndexは、パーティションキーに Subject 属性を使用し、ソートキーLastPostedDateTimeに を使用します。LSI という名前の ForumLastPostedDateIndexは、パーティションキーForumNameとして を使用し、ソートキーLastPostedDateTimeとして を使用します。

Subject 属性には 2 つの役割があることに注意してください。これは、プライマリキーのソートキーであり、 GSI という名前のパーティションキーですSubjectLastPostedDateIndex

MessageThread クラス

MessageThread クラスは、Amazon DynamoDB デベロッパーガイドサンプルスレッドテーブルのデータクラスとして使用するのに適しています。

import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbBean; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbPartitionKey; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondaryPartitionKey; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSecondarySortKey; import software.amazon.awssdk.enhanced.dynamodb.mapper.annotations.DynamoDbSortKey; import java.util.List;
@DynamoDbBean public class MessageThread { private String ForumName; private String Subject; private String Message; private String LastPostedBy; private String LastPostedDateTime; private Integer Views; private Integer Replies; private Integer Answered; private List<String> Tags; @DynamoDbPartitionKey public String getForumName() { return ForumName; } public void setForumName(String forumName) { ForumName = forumName; } // Sort key for primary index and partition key for GSI "SubjectLastPostedDateIndex". @DynamoDbSortKey @DynamoDbSecondaryPartitionKey(indexNames = "SubjectLastPostedDateIndex") public String getSubject() { return Subject; } public void setSubject(String subject) { Subject = subject; } // Sort key for GSI "SubjectLastPostedDateIndex" and sort key for LSI "ForumLastPostedDateIndex". @DynamoDbSecondarySortKey(indexNames = {"SubjectLastPostedDateIndex", "ForumLastPostedDateIndex"}) public String getLastPostedDateTime() { return LastPostedDateTime; } public void setLastPostedDateTime(String lastPostedDateTime) { LastPostedDateTime = lastPostedDateTime; } public String getMessage() { return Message; } public void setMessage(String message) { Message = message; } public String getLastPostedBy() { return LastPostedBy; } public void setLastPostedBy(String lastPostedBy) { LastPostedBy = lastPostedBy; } public Integer getViews() { return Views; } public void setViews(Integer views) { Views = views; } @DynamoDbSecondaryPartitionKey(indexNames = "ForumRepliesIndex") public Integer getReplies() { return Replies; } public void setReplies(Integer replies) { Replies = replies; } public Integer getAnswered() { return Answered; } public void setAnswered(Integer answered) { Answered = answered; } public List<String> getTags() { return Tags; } public void setTags(List<String> tags) { Tags = tags; } public MessageThread() { this.Answered = 0; this.LastPostedBy = ""; this.ForumName = ""; this.Message = ""; this.LastPostedDateTime = ""; this.Replies = 0; this.Views = 0; this.Subject = ""; } @Override public String toString() { return "MessageThread{" + "ForumName='" + ForumName + '\'' + ", Subject='" + Subject + '\'' + ", Message='" + Message + '\'' + ", LastPostedBy='" + LastPostedBy + '\'' + ", LastPostedDateTime='" + LastPostedDateTime + '\'' + ", Views=" + Views + ", Replies=" + Replies + ", Answered=" + Answered + ", Tags=" + Tags + '}'; } }

インデックスを作成する

SDK for Java のバージョン 2.20.86 以降、 createTable()メソッドはデータクラスの注釈からセカンダリインデックスを自動的に生成します。デフォルトでは、ベーステーブルのすべての属性がインデックスにコピーされ、プロビジョニングされるスループット値は 20 読み取りキャパシティーユニットと 20 書き込みキャパシティーユニットです。

ただし、2.20.86 より前のSDKバージョンを使用する場合は、次の例に示すように、インデックスをテーブルとともに構築する必要があります。この例では、Thread テーブルの 2 つのインデックスを構築します。builder パラメータには、1 行目と 2 行目のコメント行の後に示されているように、両方のタイプのインデックスを設定するメソッドがあります。インデックスビルダーの indexName() メソッドを使用して、データクラス注釈で指定されているインデックス名を目的のインデックスタイプに関連付けます。

このコードでは、すべてのテーブル属性がコメント行 3 と 4 のコメント行の後に両方のインデックスに含まれるように構成しています。属性プロジェクションの詳細については、「Amazon DynamoDB デベロッパーガイド」を参照してください。

public static void createMessageThreadTable(DynamoDbTable<MessageThread> messageThreadDynamoDbTable, DynamoDbClient dynamoDbClient) { messageThreadDynamoDbTable.createTable(b -> b // 1. Generate the GSI. .globalSecondaryIndices(gsi -> gsi.indexName("SubjectLastPostedDateIndex") // 3. Populate the GSI with all attributes. .projection(p -> p .projectionType(ProjectionType.ALL)) ) // 2. Generate the LSI. .localSecondaryIndices(lsi -> lsi.indexName("ForumLastPostedDateIndex") // 4. Populate the LSI with all attributes. .projection(p -> p .projectionType(ProjectionType.ALL)) ) );

インデックスを使用してクエリを実行する

次の例では、ローカルセカンダリインデックス をクエリしますForumLastPostedDateIndex

コメント行 2 の後に、DynamoDbIndex.query() メソッドを呼び出すときに必要なQueryConditionalオブジェクトを作成します。

コメント 3 行目の後にインデックスの名前を渡すと、クエリするインデックスへの参照が得られます。4 行目のコメントに続いて、QueryConditional オブジェクトに渡されるインデックスの query() メソッドを呼び出します。

また、5 行目のコメントの後に示される 3 つの属性値を返すようにクエリを構成します。attributesToProject() が呼び出されない場合、クエリはすべての属性値を返します。指定した属性名は小文字で始まることに注意してください。これらの属性名は表で使用されているものと一致し、必ずしもデータクラスの属性名と一致するわけではありません。

6 行目のコメントに続いて、結果を反復処理し、クエリによって返される各項目をログ記録し、それをリストに保存して呼び出し元に返します。

public static List<MessageThread> queryUsingSecondaryIndices(DynamoDbEnhancedClient enhancedClient, String lastPostedDate, DynamoDbTable<MessageThread> threadTable) { // 1. Log the parameter value. logger.info("lastPostedDate value: {}", lastPostedDate); // 2. Create a QueryConditional whose sort key value must be greater than or equal to the parameter value. QueryConditional queryConditional = QueryConditional.sortGreaterThanOrEqualTo(qc -> qc.partitionValue("Forum02").sortValue(lastPostedDate)); // 3. Specify the index name to query the DynamoDbIndex instance. final DynamoDbIndex<MessageThread> forumLastPostedDateIndex = threadTable.index("ForumLastPostedDateIndex"); // 4. Perform the query by using the QueryConditional object. final SdkIterable<Page<MessageThread>> pagedResult = forumLastPostedDateIndex.query(q -> q .queryConditional(queryConditional) // 5. Request three attribute in the results. .attributesToProject("forumName", "subject", "lastPostedDateTime")); List<MessageThread> collectedItems = new ArrayList<>(); // 6. Iterate through the pages response and sort the items. pagedResult.stream().forEach(page -> page.items().stream() .sorted(Comparator.comparing(MessageThread::getLastPostedDateTime)) .forEach(mt -> { // 7. Log the returned items and add the collection to return to the caller. logger.info(mt.toString()); collectedItems.add(mt); })); return collectedItems; }

クエリが実行される前は、次の項目がデータベースに存在しています。

MessageThread{ForumName='Forum01', Subject='Subject01', Message='Message01', LastPostedBy='', LastPostedDateTime='2023.03.28', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum02', Subject='Subject02', Message='Message02', LastPostedBy='', LastPostedDateTime='2023.03.29', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum02', Subject='Subject04', Message='Message04', LastPostedBy='', LastPostedDateTime='2023.03.31', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum02', Subject='Subject08', Message='Message08', LastPostedBy='', LastPostedDateTime='2023.04.04', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum02', Subject='Subject10', Message='Message10', LastPostedBy='', LastPostedDateTime='2023.04.06', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum03', Subject='Subject03', Message='Message03', LastPostedBy='', LastPostedDateTime='2023.03.30', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum03', Subject='Subject06', Message='Message06', LastPostedBy='', LastPostedDateTime='2023.04.02', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum03', Subject='Subject09', Message='Message09', LastPostedBy='', LastPostedDateTime='2023.04.05', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum05', Subject='Subject05', Message='Message05', LastPostedBy='', LastPostedDateTime='2023.04.01', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum07', Subject='Subject07', Message='Message07', LastPostedBy='', LastPostedDateTime='2023.04.03', Views=0, Replies=0, Answered=0, Tags=null}

1 行目と 6 行目のログ記録ステートメントは、次のようなコンソール出力になります。

lastPostedDate value: 2023.03.31 MessageThread{ForumName='Forum02', Subject='Subject04', Message='', LastPostedBy='', LastPostedDateTime='2023.03.31', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum02', Subject='Subject08', Message='', LastPostedBy='', LastPostedDateTime='2023.04.04', Views=0, Replies=0, Answered=0, Tags=null} MessageThread{ForumName='Forum02', Subject='Subject10', Message='', LastPostedBy='', LastPostedDateTime='2023.04.06', Views=0, Replies=0, Answered=0, Tags=null}

このクエリでは、Forum02forumName 値と 2023.03.31 以上の lastPostedDateTime 値の項目が返されました。インデックスには message 属性に値が含まれていますが、結果には空の文字列を含む message 値が表示されます。これは、メッセージ属性がコメント 5 行目以降に投影されなかったためです。