DynamoDB のグローバルセカンダリインデックスの管理
このセクションでは、Amazon DynamoDB でグローバルセカンダリインデックスを作成、変更、削除する方法について説明します。
トピック
グローバルセカンダリインデックスを持つテーブルの作成
1 つ以上のグローバルセカンダリインデックスを持つテーブルを作成するには、CreateTable
オペレーションと GlobalSecondaryIndexes
パラメータを使用します。最大限のクエリの柔軟性を得るために、テーブルごとに最大 20 個のグローバルセカンダリインデックス (デフォルトのクォータ) を作成できます。
インデックスパーティションキーとして機能する属性を 1 つ指定する必要があります。必要に応じて、インデックスソートキーに別の属性を指定できます。これらのキー属性のいずれも、テーブルのキー属性と同じである必要はありません。例えば、GameScores テーブル (「DynamoDB のグローバルセカンダリインデックスの使用」参照) では、TopScore
も TopScoreDateTime
もキー属性ではありません。パーティションキーとして TopScore
、ソートキーとして TopScoreDateTime
を使用して、グローバルセカンダリインデックスを作成できます。このようなインデックスを使用して、ハイスコアとゲームのプレイ時刻との間に相関があるかどうかを判定できる可能性があります。
各インデックスキー属性は、String
、Number
、または Binary
タイプのスカラーである必要があります。(ドキュメントまたはセットは指定できません)。グローバルセカンダリインデックスには、任意のデータ型の属性を射影できます。これには、スカラー、ドキュメント、およびセットが含まれます。データ型の詳細なリストについては、「データ型」を参照してください。
プロビジョニング済みモードを使用する場合は、インデックスに ReadCapacityUnits
および WriteCapacityUnits
で構成される ProvisionedThroughput
設定をする必要があります。これらのプロビジョニングされたスループット設定は、テーブルの設定とは別ですが、同様の動作をします。詳細については、「」を参照してくださいグローバルセカンダリインデックスに対するプロビジョニングされたスループットに関する考慮事項
グローバルセカンダリーインデックスは、基本テーブルから読み込み/書き込みキャパシティーモードを継承します。詳細については、「DynamoDB でキャパシティモードを切り替える際の考慮事項」を参照してください。
注記
バックフィル操作と進行中の書き込み操作で、グローバルセカンダリインデックス内の書き込みスループットが共有されます。新しい GSI を作成する際、選択したパーティションキーが、新しいインデックスのパーティションキー値全体でデータやトラフィックの分散が不均一だったり、狭くなっているかを確認することが重要になります。この場合、バックフィル操作と書き込み操作が同時に発生し、ベーステーブルへの書き込みをスロットリングしている可能性があります。このサービスでは、このシナリオの可能性を最小限に抑えるための対策を講じていますが、インデックスパーティションキー、選択した射影、またはインデックスプライマリキーのスパース性について、カスタマーデータのインサイトを見える形で取得していません。
新しいグローバルセカンダリインデックスで、パーティションキー値全体でデータやトラフィックの分散が狭められたり、歪められたりしている可能性がある場合は、運用上重要なテーブルに新しいインデックスを追加する前に、次の点を考慮してください。
-
アプリケーションのトラフィック量が最も少ない時間帯にインデックスを追加するのが、最も安全な方法と言えます。
-
ベーステーブルとインデックスで CloudWatch Contributor Insights 有効にすることを検討してください。これにより、トラフィックの分散に関する貴重なインサイトが得られます。
-
プロビジョニングされたキャパシティーモードのベーステーブルとインデックスでは、新しいインデックスのプロビジョニングされた書き込みキャパシティーをベーステーブルの少なくとも 2 倍に設定します。プロセス全体を通して、CloudWatch メトリクス
WriteThrottleEvents
、ThrottledRequests
、OnlineIndexPercentageProgress
、OnlineIndexConsumedWriteCapacity
、およびOnlineIndexThrottleEvents
を表示します。必要に応じて、プロビジョニングされた書き込みキャパシティーを調整し、進行中の操作に対してスロットリングによる大きな影響を与えることなく、適切な時間内にバックフィルを完了します。 -
書き込みスロットリングによる運用上の影響が発生した場合は、インデックスの作成をキャンセルする準備をしてください。新しい GSI のプロビジョニングされた書き込みキャパシティーを増やしてもその問題は解決しません。
テーブルのグローバルセカンダリインデックスの説明
テーブルのすべてのグローバルセカンダリインデックスのステータスを表示するには、DescribeTable
オペレーションを使用します。レスポンスの GlobalSecondaryIndexes
部分は、テーブル上のすべてのインデックスと、それぞれの現在のステータス (IndexStatus
) を示しています。
グローバルセカンダリインデックスの IndexStatus
は、次のいずれかになります。
-
CREATING
– インデックスは現在作成されていますが、まだ使用することはできません。 -
ACTIVE
– インデックスは使用可能になり、アプリケーションはインデックスに対してQuery
オペレーションを実行できます。 -
UPDATING
– インデックスのプロビジョニングされたスループット設定の変更中です。 -
DELETING
– インデックスは現在削除されているため、使用できなくなっています。
DynamoDB がグローバルセカンダリインデックスの作成を完了すると、インデックスのステータスが CREATING
から ACTIVE
に変わります。
グローバルセカンダリインデックスの既存テーブルへの追加
既存のテーブルにグローバルセカンダリインデックスを追加するには、UpdateTable
オペレーションと GlobalSecondaryIndexUpdates
パラメータを使用します。以下の情報が必要です。
-
インデックス名。名前は、テーブル内のすべてのインデックスにおいて一意である必要があります。
-
インデックスのキースキーマ。インデックスパーティションキーには 1 つの属性を指定する必要があります。必要に応じて、インデックスソートキーに別の属性を指定できます。これらのキー属性のいずれも、テーブルのキー属性と同じである必要はありません。各スキーマ属性のデータ型は、
String
、Number
、またはBinary
のスカラーである必要があります。 -
テーブルからインデックスに射影される属性は以下の通りです。
-
KEYS_ONLY
– インデックス内の各項目は、テーブルパーティションキーとソートキーの値、およびインデックスキーの値のみで構成されます。 -
INCLUDE
–KEYS_ONLY
の属性に加えて、セカンダリインデックスにその他の非キー属性が含まれるように指定できます。 -
ALL
– インデックスには、ソーステーブルのすべての属性が含まれます。
-
-
インデックスのプロビジョニングされたスループット設定で、
ReadCapacityUnits
およびWriteCapacityUnits
で構成されます。これは、テーブルのプロビジョニングされたスループット設定とは異なります。
UpdateTable
オペレーションについて作成できるグローバルセカンダリインデックスは 1 つだけです。
インデックス作成のフェーズ
新しいグローバルセカンダリインデックスを既存のテーブルに追加すると、インデックスの構築中もテーブルが使用可能になります。ただし、新しいインデックスは、そのステータスが CREATING
から ACTIVE
に変わるまでクエリオペレーションに使用できません。
注記
グローバルセカンダリインデックスの作成では、Application Auto Scaling を使用しません。MIN
Application Auto Scaling の容量を増やしても、グローバルセカンダリインデックスの作成時間は短縮されません。
その裏では、DynamoDB は 2 つのフェーズでインデックスを構築しています。
- リソース割り当て
-
DynamoDB は、インデックスの構築に必要なコンピューティングリソースとストレージリソースを割り当てます。
リソース割り当てフェーズでは、
IndexStatus
属性はCREATING
、Backfilling
属性は false です。DescribeTable
オペレーションを使用して、テーブルとそのセカンダリインデックスすべてのステータスを取得します。インデックスがリソース割り当てフェーズにある間は、インデックスやその親テーブルを削除することはできません。インデックスまたはテーブルのプロビジョニングされたスループットを変更することもできません。テーブル上の他のインデックスを追加したり削除したりすることはできません。ただし、これらの他のインデックスのプロビジョニングされたスループットは変更できます。
- バックフィル
-
テーブルの各項目について、DynamoDB は、その射影 (
KEYS_ONLY
、INCLUDE
、またはALL
) に基づいて、インデックスに書き込む属性のセットを決定します。次に、これらの属性をインデックスに書き込みます。バックフィルフェーズでは、DynamoDB はテーブルで追加、削除、または更新される項目を追跡します。これらの項目の属性も、必要に応じてインデックスで追加、削除、または更新されます。バックフィルフェーズでは、
IndexStatus
属性はCREATING
に設定されていて、Backfilling
属性は true です。DescribeTable
オペレーションを使用して、テーブルとそのセカンダリインデックスすべてのステータスを取得します。インデックスがバックフィルされている間は、親テーブルを削除することはできません。ただし、インデックスを削除したり、テーブルとそのグローバルセカンダリインデックスのプロビジョニングされたスループットを変更したりすることはできます。
注記
バックフィルフェーズでは、違反する項目の書き込みの一部が成功し、他の項目が拒否されることがあります。バックフィル後、新しいインデックスのキースキーマに違反する項目への書き込みはすべて拒否されます。バックフィルフェーズの終了後に Violation Detector ツールを実行して、発生した可能性のあるキー違反を検出して解決することをお勧めします。詳細については、「」を参照してくださいDynamoDB でのインデックスキー違反の検出と修正
リソース割り当てフェーズとバックフィルフェーズの進行中、インデックスは CREATING
状態になっています。この間、DynamoDB はテーブルに対して読み込みオペレーションを実行します。グローバルセカンダリインデックスを設定するためのベーステーブルからの読み込みオペレーションに対しては課金されません。ただし、新しく作成されたグローバルセカンダリインデックスを設定するための書き込みオペレーションに対しては課金されます。
インデックス構築が完了すると、ステータスは ACTIVE
に変わります。インデックスが ACTIVE
になるまで、Query
や Scan
はできません。
注記
場合によっては、DynamoDB は、インデックスキーの違反のため、テーブルからインデックスにデータを書き込めない場合があります。これは、以下の場合に発生します。
-
属性値のデータ型が、インデックスキーのスキーマデータ型のデータ型と一致しません。
-
属性のサイズが、インデックスキー属性の最大長を超えています。
-
インデックスキー属性には、空の文字列または空のバイナリ属性値があります。
インデックスキー違反があっても、グローバルセカンダリインデックスの作成はできます。ただし、インデックスが ACTIVE
になると、違反しているキーはインデックスに存在しなくなります。
DynamoDB には、これらの問題を検出して解決するためのスタンドアロンツールが用意されています。詳細については、「DynamoDB でのインデックスキー違反の検出と修正」を参照してください。
大きなテーブルへのグローバルセカンダリインデックスの追加
グローバルセカンダリインデックスの構築に必要な時間は、次のようないくつかの要因によって異なります。
-
テーブルのサイズ
-
インデックスに含めることができるテーブル内の項目の数
-
インデックスに射影される属性の数。
-
インデックスのプロビジョニングされた書き込み容量
-
インデックス構築中のメインテーブルへの書き込みアクティビティ
非常に大きなテーブルにグローバルセカンダリインデックスを追加する場合、作成プロセスが完了するまで時間がかかることがあります。進行状況をモニタリングし、インデックスに十分な書き込み容量があるかどうかを判断するには、次の Amazon CloudWatch メトリクスを参照してください。
-
OnlineIndexPercentageProgress
-
OnlineIndexConsumedWriteCapacity
-
OnlineIndexThrottleEvents
DynamoDB に関する CloudWatch メトリクスの詳細については、「DynamoDB のメトリクス」を参照してください。
重要
グローバルセカンダリインデックスを作成または更新する前に、非常に大きなテーブルを許可リストする必要がある場合があります。AWS サポートに連絡して、テーブルの許可リストを作成してください。
インデックスのプロビジョニングされた書き込みスループット設定が低すぎると、インデックスの構築が完了するまでに時間がかかります。プロビジョニングされた書き込み容量を一時的に増やすことにより、新しいグローバルセカンダリインデックスの構築にかかる時間を短縮することができます。
注記
原則として、インデックスのプロビジョニングされた書き込み容量をテーブルの書き込み容量の 1.5 倍に設定することをお勧めします。これは、多くのユースケースに適した設定です。ただし、実際に必要な容量がそれよりも高かったり、低かったりする可能性があります。
インデックスがバックフィルされている間、DynamoDB は内部システム容量を使用してテーブルから読み込みます。これは、インデックスの作成による影響を最小限に抑え、テーブルの読み込みキャパシティーが不足しないようにするためです。
ただし、入ってくる書き込みアクティビティのボリュームが、インデックスのプロビジョニングされた書き込み容量を超える可能性があります。この場合、インデックスへの書き込みアクティビティが抑制されるため、インデックスの作成に時間がかかります。これはボトルネックのシナリオです。インデックスの構築中に、インデックスの Amazon CloudWatch メトリクスをモニタリングして、使用された書き込み容量がプロビジョニングされた容量を超えているかどうかを判断することをお勧めします。ボトルネックのシナリオでは、バックフィルフェーズ中の書き込み抑制を回避するために、インデックスにプロビジョニングされた書き込み容量を増やすことが必要です。
インデックスの作成後、アプリケーションの通常の使用状況を反映するように、プロビジョニングされた書き込み容量を設定することが必要です。
グローバルセカンダリインデックスの削除
グローバルセカンダリインデックスが不要になった場合には、UpdateTable
オペレーションを使用して削除することができます。
グローバルセカンダリインデックスは、1 回の UpdateTable
オペレーションで 1 つだけ削除できます。
グローバルセカンダリインデックスが削除されている間、親テーブルの読み込みまたは書き込みアクティビティに影響はありません。削除の進行中でも、他のインデックスでプロビジョニングされたスループットを変更できます。
注記
-
DeleteTable
アクションを使用してテーブルを削除すると、そのテーブルのすべてのグローバルセカンダリインデックスも削除されます。 -
アカウントではグローバルセカンダリインデックスの削除操作に対して課金されません。
作成時のグローバルセカンダリインデックスの変更
インデックスが作成されている間は、DescribeTable
オペレーションを使用して、どのフェーズにあるかを判断します。インデックスの説明に含まれているブール属性 Backfilling
は、DynamoDB がテーブルから項目を含むインデックスを現在ロードしているかどうかを示します。Backfilling
が true の場合、リソース割り当てフェーズは完了していて、インデックスがバックフィルされています。
バックフィルが進行している間は、インデックスのプロビジョニングされたスループットパラメータを更新できます。インデックスの構築を高速化するために、インデックスの作成中にインデックスの書き込み容量を増やし、後で減らすこともできます。インデックスのプロビジョニングされたスループット設定を変更するには、UpdateTable
オペレーションを使用します。インデックスのステータスが UPDATING
に変わります。インデックスが使用可能になるまで、Backfilling
は true です。
バックフィルフェーズでは、作成中のインデックスを削除できます。このフェーズでは、テーブルの他のインデックスを追加または削除することはできません。
注記
CreateTable
オペレーションの一部として作成されたインデックスの場合、Backfilling
属性は DescribeTable
出力に現れません。詳細については、「インデックス作成のフェーズ」を参照してください。