DynamoDB のグローバルセカンダリインデックス(GSI)
キーのないアクセスパターンごとに GSI を足し、書き込みコストが 3 倍になって目覚め、 強整合を想定したせいでインデックスから古い行をまだ読む。グローバルセカンダリ インデックスは AWS が維持してくれる第 2 のテーブルだ — 同じ課金ルール、結果整合の 読み取りのみ、すべてのベーステーブル put での書き込み増幅。
毎秒 100 書き込みの 1 KB アイテム、us-east-1 オンデマンドでは、インデックスなしで
書き込みは月 $164.25、GSI 1 つで $328.50、2 つで $492.75。足す各 ALL 射影 GSI が
書き込みスループットを買い直す。
読み終えたらできること
- 2 つ目や 3 つ目のインデックスにコミットする前に GSI 書き込み増幅を見積もれる。
- 特定のアクセスパターンに対して GSI 対 LSI 対フィルター式を選べる。
- 結果が半分の RCU レートで結果整合であることを知りつつ GSI から読める。
- 射影とクォータ上限を破らずにスパースキーとオーバーロードキーを設計できる。
読む順番
- GSI 対 LSI — 再パーティション化された読み取り対 同じハッシュの代替ソート。作成時ルールと 10 GB LSI コレクション上限。
- インデックス射影 —
ALL、KEYS_ONLY、INCLUDE。ストレージと書き込みサイズのトレードオフ。 - スパースインデックス — 冷たい行でインデックス キーを省略し、ホットな部分集合だけがコピーされるようにする。
- キーのオーバーロード — 規律あるキー形で 複数のアクセスパターンを 1 つの GSI に詰める。
- GSI の結果整合 — read-your-writes の失敗と、ベーステーブル読み取りが必要な UI パターン。
- GSI がベーステーブルをスロットルする — プロビジョニング不足のインデックスキャパシティが親の書き込みをブロックする。
グローバルセカンダリインデックスとは?
GSI は、任意のトップレベル String、Number、または Binary 属性から選んだ
独自のパーティションキーと任意のソートキーを持つインデックスだ。インデックスキーは
テーブルのキーを含む必要はない。
DynamoDB がコピーを維持する。アイテムを put、update、delete すると、影響を受ける
すべての GSI が非同期に更新される。インデックスへ直接書くことはない。インデックス名に
対する Query または Scan で読む。
| field | value | note |
|---|---|---|
| PK | "CUST#9313" | table partition key |
| SK | "ORD#2026-08-01#K4" | table sort key |
| status | "SHIPPED" | GSI partition key |
| placed | "2026-08-01" | GSI sort key |
status-placed GSI を status = "PENDING" でクエリすると、すべての顧客にまたがる
保留中の注文を日付順で得る。ベーステーブルは Scan なしではそれに答えられない。
インデックスキー属性を欠くアイテムは、単にインデックスに存在しない。その隙間を スパースインデックス が利用し、巨大テーブルの 小さなホット部分集合を、それ自体の事前フィルターされたコレクションに変える。
GSI はいくらかかるか?
書き込み側が支配する。1 KB アイテムは 1 書き込み
キャパシティユニット(書き込みは 1 KB ごとに切り上げ)で、
ALL 射影ならすべてのベーステーブル書き込みがすべての GSI へ繰り返される。
3 つの持続書き込みレートで計測:
| 持続書き込み | GSI 0 | GSI 1 | GSI 2 |
|---|---|---|---|
| 10 writes/s | $16.43/mo | $32.85/mo | $49.28/mo |
| 100 writes/s | $164.25/mo | $328.50/mo | $492.75/mo |
| 1,000 writes/s | $1,642.50/mo | $3,285.00/mo | $4,927.50/mo |
最大 1 KB のアイテム、オンデマンド、us-east-1、AWS 公開の百万書き込みリクエスト ユニットあたり $0.625(2026-07-29 の料金同期)。10 writes/s は 730 時間の請求月で 2,628 万 WRU。
GSI 列は正確な倍数ではなく下限として読む。インデックスアイテムはベーステーブルの キー、インデックス自身のキー、約 100 バイトのオーバーヘッドを運ぶので、1 KB の線に近い ベースアイテムは各インデックスへ 1 ではなく 2 WRU を書く — ×2 と ×3 はそこから増える。
GSI キー値を変える更新は 2 回のインデックス書き込みを請求する — 古いエントリを 削除する 1 回と新しいものを put する 1 回 — なので揮発性のインデックスキーは 安定したものより高い。
ストレージも繰り返す。ALL 射影は us-east-1 で月 $0.25/GB(同じ同期)でテーブルを
再格納し、インデックスアイテムあたり 100 バイトのオーバーヘッドが加わる。10 GB の
テーブルは GSI あたり月 $2.50 の追加だ。
射影 を KEYS_ONLY または INCLUDE に縮めると両方の請求が縮む。
インデックス射影 を参照。
プロビジョンドモードでは同じ増幅がキャパシティとして現れ、プロビジョニング不足の GSI がベーステーブルの書き込みをスロットルする。 なぜ GSI がベーステーブルの書き込みをスロットルするか がその失敗を歩く。
自分のワークロードを見積もるには、 料金計算機 が上の数字と同じ料金表で走る。
GSI が読み取りをどう課金するか
GSI の読み取りは常に 結果整合 で、結果整合の読み取りは 半額レートで課金される。4 KB あたり 0.5 RCU。
二十個の 1 KB アイテムを返す Query は合計 20 KB、五つの 4 KB ユニットに切り上げ、
2.5 RCU を請求する。同じ二十アイテムをベーステーブルから強整合で読むと 5 RCU。
半額はラグを買う。変更は GSI へ「通常条件では一瞬のうちに」(AWS の文言)伝播し、
それを待ち切る ConsistentRead オプションはない。
コードが自分の書き込みを GSI 経由で読み戻すなら、本番で刺さる前に なぜ GSI は結果整合か を読む。
GSI 対 LSI 対フィルター式
| あなたのアクセスパターン | 手に取るもの | なぜ |
|---|---|---|
| テーブルキーではない属性でクエリする | GSI | 再パーティション化する唯一のインデックス。ライブテーブルへいつでも追加できる |
| 同じパーティション内の第 2 ソート順、強整合読み取り | LSI | テーブルキャパシティを共有し ConsistentRead をサポート。作成時のみ、10 GB コレクション上限 |
| 巨大テーブルの小さなホット部分集合をクエリする | スパース GSI | インデックスキーを運ぶアイテムだけがコピーされ、インデックスが小さく安く保たれる |
すでに安い 1 回の Query である結果セットを絞る | フィルター式 | 維持するコピーはないが、捨てる各アイテムを読む分は支払う |
| 二度と聞かないワンオフの質問 | インデックスなし | Scan またはエクスポートは一度のコスト。インデックスは毎月コストがかかる |
LSI の上限は聞こえるより厳しい。パーティションキー値あたり 10 GB はベーステーブル アイテムとそのキーを持つすべての LSI エントリを数え、コレクションがそれに達すると DynamoDB は書き込みを拒否する。
それと作成時のみのルールが、正直な既定が GSI である理由だ。 GSI 対 LSI が全体の論を立てる。
インデックス設計を形づくる上限
- テーブルあたり 20 GSI: 既定クォータ。Service Quotas 経由で調整可能。
- テーブルあたり 5 LSI: 固定で、
CreateTable時のみ。あとから追加できない。 - 100 の射影属性: テーブルの全インデックスにまたがる
INCLUDE属性の合計。KEYS_ONLYとALL射影はそれにカウントされない。 QueryとScanのみ:GetItemとBatchGetItemはどのセカンダリ インデックスでも動かない。- GSI からのベーステーブル取得なし: GSI クエリは射影された属性だけを返す。 LSI クエリは追加の読み取りコストで未射影属性を取得できる。
- インデックスキーはトップレベルのスカラー:
String、Number、またはBinary。セット、リスト、マップ、ネスト属性は不可。
稼働中のテーブルに GSI を追加する
LSI と違い、GSI はすでにトラフィックを捌いているテーブルにも追加できる。
UpdateTable は 1 回の呼び出しにつきインデックスの作成または削除を 1 つ受け付け、
その間テーブルは ACTIVE のままだ。DynamoDB は新しいインデックスを 2 つのフェーズで
構築する — まずインデックスのリソースが作られ、次にインデックスキー属性を持つ
既存アイテムがすべてそこへバックフィルされる。
バックフィルについては、3 つの点が見落とされやすい:
- 完了するまでインデックスをクエリできない。 インデックスは
CREATINGを報告し (コピーが始まるとBackfillingフラグが立つ)、ステータスがACTIVEになるまで そのインデックスへのQueryは拒否される。 - バックフィルの読み取りは無料だが、インデックスへの書き込みは実費だ。 DynamoDB は 既存アイテムを内部キャパシティで読むので、その走査はテーブルに課金されない — だが 各アイテムはインデックス自身の書き込みキャパシティを通ってインデックスに入る。 プロビジョニング不足の GSI はバックフィルを這うような速度に変える。オンデマンドの テーブルならキャパシティは自動で合わせられる。
- 所要時間はテーブルサイズに比例する。 小さなテーブルなら数分、数百ギガバイトを
抱えるテーブルなら数時間。
DescribeTableが報告するのはフェーズであって、 進捗率ではない。
よくある質問
既存の DynamoDB テーブルに GSI を追加できるか?
できる。GSI は UpdateTable でいつでも稼働中のテーブルに追加でき、1 回の呼び出しに
つきインデックスは 1 つ、DynamoDB がインデックスをバックフィルするあいだもテーブルは
読み書きを受け付け続ける。テーブル作成時に固定されるのは LSI だけだ。
GSI のバックフィルにはどれくらいかかるか?
テーブルサイズとインデックスの書き込みキャパシティ次第だ — 小さなテーブルなら数分、
大きなテーブルなら数時間。バックフィルが終わるまでインデックスは CREATING を報告し、
ステータスが ACTIVE になるまでそのインデックスへのクエリは拒否される。
作成したあとに GSI を変更できるか? できない。既存の GSI のキーや射影を変える手段は DynamoDB にない — 望む形の代わりの インデックスを作り、読み取り側をそちらへ移し、古いほうを削除する。例外は プロビジョンドスループットで、これはその場で更新できる。
既存のテーブルに LSI を追加できるか?
できない。LSI は CreateTable で宣言した場合にのみ存在し、あとからどんなツールでも
追加できない。既存のテーブルで第 2 ソート順が必要なら、答えは同じパーティションキーを
持つ GSI だ。
DynoTable を開く
DynoTable のテーブル設定ダイアログはテーブルのキー構造と、キー付きのすべての GSI と LSI を
一覧するので、自分で DescribeTable を走らせずに、テーブルがすでにどのアクセス
パターンを満たすかが見える。

ビジュアルなフィルタービルダーにはインデックスピッカーがあり、条件を足すにつれて
Query 対 Scan を導出するので、フル Scan への高いフォールバックが何も走らせる前に
見える。

同じダイアログから GSI の作成と削除もできる。キースキーマを指定し、ALL /
KEYS_ONLY / INCLUDE の射影を選び、プロビジョンドテーブルではインデックスごとの
スループットを設定し、DynamoDB がインデックスを構築するあいだ Creating/Backfilling の
ライブステータスを眺める。LSI は読み取り専用で一覧される — それは DynamoDB のルール
であってツールの制約ではない — また既存の GSI は置き換えられるが編集はできない。
テーブル管理は有料プランの機能で、トライアルにも含まれる。
DynoTable をダウンロードしてインデックスを直接調べてクエリし、 シングルテーブル設計プランナー でアクセス パターンの一覧を、コミット前に PK/SK/GSI レイアウトへ変えよう。





