

# ローカルセカンダリインデックス
<a name="LSI"></a>

ベーステーブルのプライマリキーを使用してデータのクエリを実行する必要があるのは、一部のアプリケーションだけです。ただし、代替のソートキーが役に立つ場合があります。アプリケーションでソートキーを選択できるようにするには、Amazon DynamoDB テーブルに 1 つ以上のローカルセカンダリインデックスを作成し、これらのインデックスに対して `Query` または `Scan` のリクエストを発行できます。

**Topics**
+ [シナリオ: ローカルセカンダリインデックスの使用](#LSI.Scenario)
+ [属性の射影](#LSI.Projections)
+ [ローカルセカンダリインデックスの作成](#LSI.Creating)
+ [ローカルセカンダリインデックスからのデータの読み込み](#LSI.Reading)
+ [項目の書き込みとローカルセカンダリインデックス](#LSI.Writes)
+ [ローカルセカンダリインデックスに対するプロビジョニングされたスループットに関する考慮事項](#LSI.ThroughputConsiderations)
+ [ローカルセカンダリインデックスのストレージに関する考慮事項](#LSI.StorageConsiderations)
+ [ローカルセカンダリインデックス内の項目コレクション](#LSI.ItemCollections)
+ [ローカルセカンダリインデックスの操作: Java](LSIJavaDocumentAPI.md)
+ [ローカルセカンダリインデックスの操作: .NET](LSILowLevelDotNet.md)
+ [DynamoDB AWS CLI でのローカルセカンダリインデックスの操作](LCICli.md)

## シナリオ: ローカルセカンダリインデックスの使用
<a name="LSI.Scenario"></a>

例として、`Thread` テーブルを検討します。このテーブルは、[AWS ディスカッションフォーラム](https://forums.aws.amazon.com/)のようなアプリケーションで役立ちます。次の図は、テーブル内の項目の構成を示しています。一部表示されていない属性もあります。

![フォーラム名、件名、最後の投稿時刻、および返信数のリストを含む Thread テーブル。](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/LSI_01.png)


DynamoDB には、同じパーティションキー値を持つすべての項目が継続的に保存されます。この例では、特定の `ForumName` を指定すると、`Query` オペレーションはそのフォーラムのすべてのスレッドをすばやく見つけることができます。同じパーティションキー値を持つ項目のグループでは、項目がソートキーの値によって並べ替えられます。ソートキー (`Subject`) がクエリでも提供される場合、DynamoDB は返される結果を絞り込むことができます。例えば、「S3」フォーラムで、文字「a」で始まる `Subject` を持つすべてのスレッドを返すことができます。

リクエストによっては、より複雑なデータアクセスパターンが要求される場合があります。以下に例を示します。
+ ビューと返信の数が最も多いのはどのフォーラムか?
+ 特定のフォーラムでメッセージ数が最も多いのはどのスレッドか?
+ 特定の期間中に特定のフォーラムに投稿されたスレッド数は?

これらの質問に答えるには、`Query` アクションでは十分ではありません。代わりに、テーブル全体の `Scan` を実行する必要があります。膨大な数の項目があるテーブルでは、これにより、プロビジョニングされた読み込みスループットが大量に消費されることになり、完了するまでに長時間かかります。

ただし、`Replies` や `LastPostDateTime` などの非キー属性に 1 つ以上のローカルセカンダリインデックスを指定することができます。

*ローカルセカンダリインデックス*は特定のパーティションキー値の代替ソートキーを維持します。またローカルセカンダリインデックスには、ベーステーブルの一部またはすべての属性のコピーが含まれます。テーブルを作成する際に、ローカルセカンダリインデックスに射影する属性を指定します。ローカルセカンダリインデックスのデータは、ベーステーブルと同じパーティションキーと、異なるソートキーで構成されます。これにより、この異なるディメンションにわたってデータ項目に効率的にアクセスできます。クエリまたはスキャンの柔軟性を向上させるために、テーブルごとに最大 5 つのローカルセカンダリインデックスを作成できます。

たとえば、あるアプリケーションで、特定のフォーラムに過去 3 か月以内に投稿されたすべてのスレッドを検索する必要があるとします。ローカルセカンダリインデックスがない場合、アプリケーションは `Scan` テーブル全体の `Thread` を実行して、指定された時間枠から外れた投稿を破棄する必要があります。ローカルセカンダリインデックスがあれば、`Query` オペレーションでは `LastPostDateTime` をソートキーとして使用し、データをすばやく見つけることができます。

次の図は、`LastPostIndex` という名前のローカルセカンダリインデックスを示しています。パーティションキーは `Thread` テーブルのパーティションキーと同じですが、ソートキーは `LastPostDateTime` です。

![フォーラム名、件名、および最後の投稿時刻のリストを含む LastPostIndex テーブル。](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/LSI_02.png)


ローカルセカンダリインデックスは、すべて次の条件を満たす必要があります。
+ パーティションキーはそのベーステーブルのパーティションキーと同じである。
+ ソートキーは完全に 1 つのスカラー属性で構成されている。
+ ベーステーブルのソートキーがインデックスに射影され、非キー属性として機能する。

この例で、パーティションキーは `ForumName`、ローカルセカンダリインデックスのソートキーは `LastPostDateTime` です。さらに、ベーステーブルのソートキーの値 (この例では `Subject`) がインデックスに射影されますが、その値はインデックスキーの一部ではありません。アプリケーションが `ForumName` と `LastPostDateTime` に基づくリストを必要とする場合は、`Query` に対して `LastPostIndex` リクエストを実行できます。クエリ結果は `LastPostDateTime` によってソートされ、昇順または降順で返すことができます。このクエリは、特定の時間枠内に `LastPostDateTime` がある項目だけを返すなどのキー条件を適用することもできます。

すべてのローカルセカンダリインデックスには、そのベーステーブルからのパーティションキーとソートキーが自動的に格納されます。必要に応じて、非キー属性をインデックスに射影できます。インデックスのクエリを行うと、DynamoDB ではこれらの射影された属性を効率的に取り出すことができます。ローカルセカンダリインデックスにクエリを実行すると、インデックスに射影されて*いない*属性もクエリで取得できます。DynamoDB では、これらの属性をベーステーブルから自動的にフェッチしますが、レイテンシーが大きくなり、プロビジョニングされたスループットコストが高くなります。

任意のローカルセカンダリインデックスについて、異なるパーティションキーの値ごとに最大 10 GB のデータを保存できます。この数字には、ベーステーブル内のすべての項目に加えて、同じパーティションキーの値を持つインデックス内のすべての項目も含まれています。詳細については、「[ローカルセカンダリインデックス内の項目コレクション](#LSI.ItemCollections)」を参照してください。

## 属性の射影
<a name="LSI.Projections"></a>

`LastPostIndex` では、アプリケーションはクエリの基準として `ForumName` と `LastPostDateTime` を使用できます。ただし、追加の属性を取得する場合、DynamoDB は `Thread` テーブルに対して追加の読み取りオペレーションを実行する必要があります。このような追加の読み込みを*フェッチ*と言い、それによってクエリにプロビジョニングするスループットの合計量が増加することがあります。

ウェブページに「S3」内のすべてのスレッドと各スレッドの返信のリストを表示し、最新の返信の最後の返信日時で並べ替えるとします。このリストに入力するには、次の属性が必要になります。
+ `Subject`
+ `Replies`
+ `LastPostDateTime`

このデータのクエリを最も効率的に行い、フェッチオペレーションを回避するには、次の図に示すように、ローカルセカンダリインデックスにテーブルからの `Replies` 属性を射影します。

![フォーラム名、最後の投稿時刻、件名、および返信のリストを含む LastPostIndex テーブル。](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/LSI_03.png)




*射影*とは、テーブルからセカンダリインデックスにコピーされる属性のセットです。テーブルのパーティションキーとソートキーは常にインデックスに射影されます。アプリケーションのクエリ要件をサポートするために、他の属性を射影できます。インデックスをクエリすると、Amazon DynamoDB は、その属性が自身のテーブル内にあるかのように、プロジェクション内の任意の属性にアクセスできます。

セカンダリインデックスを作成するときは、インデックスに射影される属性を指定する必要があります。DynamoDB には、そのために次の 3 つのオプションが用意されています。
+ *KEYS\_ONLY* – インデックス内の各項目は、テーブルパーティションキーとソートキーの値、およびインデックスキーの値のみで構成されます。`KEYS_ONLY` オプションを指定すると、セカンダリインデックスが最小になります。
+ *INCLUDE* – `KEYS_ONLY` の属性に加えて、セカンダリインデックスにその他の非キー属性が含まれるように指定できます。
+ *ALL* – セカンダリインデックスには、ソーステーブルのすべての属性が含まれます。すべてのテーブルデータがインデックスに複製されるため、`ALL` の射影にすると、セカンダリインデックスが最大になります。

前の図では、非キー属性の `Replies` が `LastPostIndex` に射影されています。アプリケーションでは `LastPostIndex` テーブル全体ではなく `Thread` に対するクエリを実行し、ウェブページに `Subject`、`Replies`、`LastPostDateTime` を表示することができます。他の非キー属性がリクエストされた場合、DynamoDB はそれらの属性を `Thread` テーブルからフェッチする必要があります。

アプリケーションの観点から見ると、ベーステーブルから追加の属性をフェッチする処理は、自動的で透過的なので、アプリケーションロジックを書き直す必要はありません。ただし、このようなフェッチによって、ローカルセカンダリインデックスを使用することで得られるパフォーマンスの利点が大幅に小さくなる可能性があります。

ローカルセカンダリインデックスに射影する属性を選択する場合には、プロビジョニングされるスループットコストとストレージコストのトレードオフを考慮する必要があります。
+ ごく一部の属性だけに最小のレイテンシーでアクセスする必要がある場合は、それらの属性だけをローカルセカンダリインデックスに射影することを検討してください。インデックスが小さいほど少ないコストで格納でき、書き込みコストも低くなります。まれにしかフェッチされない属性がある場合には、それらの属性を格納するコストよりも、プロビジョニングされるスループットのコストのほうが長期的に大きくなる可能性があります。
+ アプリケーションが非キー属性に頻繁にアクセスする場合には、それらの属性をローカルセカンダリインデックスに射影することを検討してください。ローカルセカンダリインデックスのストレージコストの増加は、頻繁にテーブルスキャンを実行するコストの減少で相殺されます。
+ ほとんどの非キー属性に頻繁にアクセスする場合は、それらの属性を (場合によっては、ベーステーブル全体を) ローカルセカンダリインデックスに射影することができます。それによってフェッチが不要になるため、柔軟性が最大になり、プロビジョニングされるスループットが最小限になります。ただし、ストレージコストが増加し、すべての属性を射影する場合には 2 倍にまで増大します。
+ アプリケーションでテーブルのクエリを頻繁に行う必要がなく、テーブル内のデータに対する書き込みや更新が多数になる場合は、*KEYS\_ONLY* を射影することを検討してください。ローカルセカンダリインデックスは、最小サイズになりますが、それでもクエリのアクティビティに必要な場合は利用可能です。

## ローカルセカンダリインデックスの作成
<a name="LSI.Creating"></a>

テーブルで 1 つ以上のローカルセカンダリインデックスを作成するには、`CreateTable` オペレーションの `LocalSecondaryIndexes` パラメータを使用します。テーブルのローカルセカンダリインデックスは、テーブルが作成された時点で作成されます。テーブルを削除すると、そのテーブルにあるローカルセカンダリインデックスも削除されます。

ローカルセカンダリインデックスのソートキーにとなる 1 つの非キー属性を指定する必要があります。選択する属性はスカラー `String`、`Number`、または `Binary` である必要があります。その他のスカラー型、ドキュメント型、およびセット型は許可されません。データ型の詳細なリストについては、「[データ型](HowItWorks.NamingRulesDataTypes.md#HowItWorks.DataTypes)」を参照してください。

**重要**  
ローカルセカンダリインデックスがあるテーブルには、パーティションキーの値ごとに 10 GB のサイズ制限があります。ローカルセカンダリインデックスがあるテーブルには、1 つのパーティションキー値の合計サイズが 10 GB を超えない限り、任意の数の項目を格納できます。詳細については、「」を参照してください[項目コレクションのサイズ制限](#LSI.ItemCollections.SizeLimit)

ローカルセカンダリインデックスには、任意のデータ型の属性を射影できます。これには、スカラー、ドキュメント、およびセットが含まれます。データ型の詳細なリストについては、「[データ型](HowItWorks.NamingRulesDataTypes.md#HowItWorks.DataTypes)」を参照してください。

## ローカルセカンダリインデックスからのデータの読み込み
<a name="LSI.Reading"></a>

`Query` および `Scan` オペレーションを使用して、ローカルセカンダリインデックスから項目を取得できます。`GetItem` および `BatchGetItem` オペレーションは、ローカルセカンダリインデックスでは使用できません。

### ローカルセカンダリインデックスのクエリ
<a name="LSI.Querying"></a>

DynamoDB テーブルでは、各項目のパーティションキー値とソートキー値の組み合わせは、一意である必要があります。ただし、ローカルセカンダリインデックスでは、ソートキーの値は、特定のパーティションキーの値に対して一意である必要がありません。ローカルセカンダリインデックスに同じソートキーを持つ複数の項目がある場合、`Query` オペレーションは、同じパーティションキーの値を持つすべての項目を返します。レスポンスでは、一致する項目は特定の順序で返されません。

結果整合性の読み込みまたは完全整合性の読み込みを使用して、ローカルセカンダリインデックスのクエリを行うことができます。必要な整合性のタイプを指定するには、`ConsistentRead` オペレーションの `Query` パラメータを使用します。ローカルセカンダリインデックスからの完全整合性の読み込みでは、常に最新の更新された値が返されます。クエリがベーステーブルからさらに属性をフェッチする必要がある場合、それらの属性はインデックスについて整合性があることになります。

**Example**  
特定のフォーラムのディスカッションスレッドにあるデータをリクエストする `Query` から返される次のデータを考えてみます。  

```
{
    "TableName": "Thread",
    "IndexName": "LastPostIndex",
    "ConsistentRead": false,
    "ProjectionExpression": "Subject, LastPostDateTime, Replies, Tags",
    "KeyConditionExpression": 
        "ForumName = :v_forum and LastPostDateTime between :v_start and :v_end",
    "ExpressionAttributeValues": {
        ":v_start": {"S": "2015-08-31T00:00:00.000Z"},
        ":v_end": {"S": "2015-11-31T00:00:00.000Z"},
        ":v_forum": {"S": "EC2"}
    }
}
```
このクエリでは次のようになっています。  
+ DynamoDB は `ForumName` パーティションキーを使用して `LastPostIndex` にアクセスし、「EC2」のインデックス項目を特定します。このキーを持つすべてのインデックス項目が、すばやく取り出せるように隣り合わせに格納されます。
+ このフォーラム内で、DynamoDB はインデックスを使用して、指定された `LastPostDateTime` 条件に一致するキーを検索します。
+ `Replies` 属性はインデックスに射影されているため、DynamoDB は追加でプロビジョニングされたスループットを使用することなく、この属性を取得できます。
+ `Tags` 属性はインデックスに射影されていないため、DynamoDB は `Thread` テーブルにアクセスしてこの属性をフェッチする必要があります。
+ 結果が、`LastPostDateTime` によってソートされ、返されます。インデックスのエントリはまずパーティションキーの値によって、次にソートキーの値によって並べ替えられ、保存される順序で `Query` から返されます （`ScanIndexForward` パラメータを使用すると、結果が降順で返されます）。
ローカルセカンダリインデックスには `Tags` 属性が射影されていないため、DynamoDB は、読み取りキャパシティユニットを追加で使用して、ベーステーブルからこの属性をフェッチする必要があります。このクエリを頻繁に実行する必要がある場合は、`Tags` 属性を `LastPostIndex` に射影して、ベーステーブルからフェッチされないようにする必要があります。ただし、`Tags` 属性をまれにしか使用しない場合は、`Tags` 属性をインデックスに射影するためにストレージを追加することが有効でない可能性があります。

### ローカルセカンダリインデックスのスキャン
<a name="LSI.Scanning"></a>

`Scan` を使用して、ローカルセカンダリインデックスからすべてのデータを取得できます。リクエストにはベーステーブル名とインデックス名を指定する必要があります。`Scan` では、DynamoDB はインデックスのすべてのデータを読み込み、それをアプリケーションに返します。また、データの一部のみを返し、残りのデータを破棄するようにリクエストすることもできます。これを行うには、`FilterExpression` API の `Scan` パラメータを使用します。詳細については、「[Scan のフィルタ式](Scan.md#Scan.FilterExpression)」を参照してください。

## 項目の書き込みとローカルセカンダリインデックス
<a name="LSI.Writes"></a>

DynamoDB によって、すべてのローカルセカンダリインデックスがそれぞれのベーステーブルと自動的に同期されます。アプリケーションがインデックスに直接書き込むことはありません。ただし、DynamoDB でこれらのインデックスがどのように維持されるかを理解することは重要です。

ローカルセカンダリインデックスを作成する場合は、インデックスのソートキーになる属性を指定します。その属性のデータ型も指定します。つまり、ベーステーブルに項目を書き込むとき、その項目にインデックスキー属性が定義されている場合は、その型がインデックスキースキーマのデータ型に一致する必要があります。`LastPostIndex` の場合、インデックス内の `LastPostDateTime` ソートキーは、`String` データ型として定義されています。`Thread` テーブルに項目を追加し、`LastPostDateTime` に対して別のデータ型を指定する場合 (`Number` など)、データ型の不一致により DynamoDB によって `ValidationException` が返されます。

ベーステーブル内の項目とローカルセカンダリインデックス内の項目を 1 対 1 の関係にする必要はありません。この動作は、多くのアプリケーションにとってメリットになります。

多数のローカルセカンダリインデックスがあるテーブルは、インデックス数が少ないテーブルに比べて書き込みアクティビティに多くのコストを要します。詳細については、「[ローカルセカンダリインデックスに対するプロビジョニングされたスループットに関する考慮事項](#LSI.ThroughputConsiderations)」を参照してください。

**重要**  
ローカルセカンダリインデックスがあるテーブルには、パーティションキーの値ごとに 10 GB のサイズ制限があります。ローカルセカンダリインデックスがあるテーブルには、1 つのパーティションキー値の合計サイズが 10 GB を超えない限り、任意の数の項目を格納できます。詳細については、「[項目コレクションのサイズ制限](#LSI.ItemCollections.SizeLimit)」を参照してください。

## ローカルセカンダリインデックスに対するプロビジョニングされたスループットに関する考慮事項
<a name="LSI.ThroughputConsiderations"></a>

DynamoDB にテーブルを作成する場合には、テーブルで予想されるワークロードに応じた読み込み/書き込みキャパシティーユニットをプロビジョニングします。このワークロードには、テーブルのローカルセカンダリインデックスの読み込み/書き込みアクティビティが含まれます。

プロビジョニングされたスループット容量の現在の料金を確認するには、「[Amazon DynamoDB 料金](https://aws.amazon.com/dynamodb/pricing)」を参照してください。

### 読み込みキャパシティユニット
<a name="LSI.ThroughputConsiderations.Reads"></a>

ローカルセカンダリインデックスに対してクエリを実行する場合、使用される読み込みキャパシティーユニットの数は、データのアクセス方法によって異なります。

テーブルに対するクエリと同様に、インデックスクエリでは `ConsistentRead` の値に応じて、結果整合性のある読み込みまたは強力な整合性のある読み込みを実行できます。1 回の強力な整合性のある読み込みでは、1 つの読み込みキャパシティーユニットが消費され、結果整合性のある読み込みではその半分が消費されます。したがって結果整合性のある読み込みを選択することで、読み込みキャパシティーユニットのコストを削減できます。

インデックスキーと射影された属性だけをリクエストするインデックスクエリの場合、DynamoDB はテーブルに対するクエリの場合と同じ方法で、プロビジョニングされた読み込みアクティビティを計算します。唯一の違いは、ベーステーブル内の項目のサイズではなくインデックスエントリのサイズに基づいて計算が行われることです。読み込みキャパシティーユニットの数は、返されたすべての項目について射影されたすべての属性のサイズの合計です。結果は、次の 4 KB 境界まで切り上げられます。DynamoDB がプロビジョニングされたスループットの利用率を計算する方法の詳細については、「[DynamoDB プロビジョンドキャパシティモード](provisioned-capacity-mode.md)」を参照してください。

ローカルセカンダリインデックスに射影されていない属性を読み込むインデックスクエリの場合、DynamoDB は射影された属性をインデックスから読み込むのに加えて、それらの属性をベーステーブルからフェッチする必要があります。これらのフェッチは、`Select` オペレーションの `ProjectionExpression` または `Query` パラメータに、射影されていない属性を含めた場合に実行されます。フェッチによってクエリ応答のレイテンシーが増加し、プロビジョニングされるスループットのコストも増加します。前述のローカルセカンダリインデックスからの読み込みに加えて、フェッチされるベーステーブル項目それぞれについて、読み込みキャパシティーユニットの料金がかかります。この料金は、リクエストした属性だけでなく、項目全体をテーブルから読み込むために発生するものです。

`Query` オペレーションによって返される結果の最大サイズは 1 MB です。これには、返されるすべての項目にわたる、すべての属性の名前と値のサイズが含まれます。ただし、ローカルセカンダリインデックスに対するクエリによって、DynamoDB がベーステーブルから項目の属性をフェッチする場合には、結果で示されるデータの最大サイズが小さくなる可能性があります。この場合、結果のサイズは次の合計になります。
+ インデックス内で一致する項目のサイズ (次の 4 KB に切り上げ)
+ ベーステーブル内で一致する各項目のサイズ (項目ごとに次の 4 KB に切り上げ)

この式を使用すると、クエリオペレーションによって返される結果の最大サイズは依然として 1 MB になります。

たとえば、各項目のサイズが 300 バイトであるテーブルがあるとします。そのテーブルにはローカルセカンダリインデックスがありますが、各項目のうち 200 バイトだけがインデックスに射影されます。このインデックスに対して `Query` を行うときに各項目についてテーブルのフェッチが必要で、クエリによって 4 つの項目が返されるとします。DynamoDB では、次のように合計されます。
+ インデックス内で一致する項目のサイズは 200 バイト × 4 項目 = 800 バイトになり、それが 4 KB に切り上げられます。
+ ベーステーブル内で一致する項目のサイズ: (300 バイト、4 KB に切り上げ) × 4 項目 = 16 KB。

それによって、結果データの合計サイズは 20 KB になります。

### 書き込みキャパシティユニット
<a name="LSI.ThroughputConsiderations.Writes"></a>

テーブル内の項目が追加、更新、または削除された場合にローカルセカンダリインデックスを更新すると、テーブルにプロビジョニングされた書き込みキャパシティーユニットが消費されます。書き込み用にプロビジョニングされたスループットの合計コストは、テーブルに対する書き込みと、ローカルセカンダリインデックスの更新で消費された書き込みキャパシティーユニットの合計になります。

ローカルセカンダリインデックスに項目を書き込むコストは、いくつかの要因に左右されます。
+ インデックス付き属性が定義されたテーブルに新しい項目を書き込む場合、または既存の項目を更新して未定義のインデックス付き属性を定義する場合には、インデックスへの項目の挿入に 1 回の書き込みオペレーションが必要です。
+ テーブルに対する更新によってインデックス付きキー属性の値が（A から B に）変更された場合には、インデックスから既存の項目を削除し、インデックスに新しい項目を挿入するために、2 回の書き込みが必要です。  
+ インデックス内に既存の項目があって、テーブルに対する書き込みによってインデックス付き属性が削除された場合は、インデックスから古い項目の射影を削除するために、1 回の書き込みが必要です。
+ 項目の更新の前後にインデックス内に項目が存在しない場合は、インデックスで追加の書き込みコストは発生しません。

これらすべての要因は、インデックス内の各項目のサイズが 1 KB 以下であるという前提で書き込みキャパシティーユニット数を算出します。インデックスエントリがそれよりも大きい場合は、書き込みキャパシティーユニットを追加する必要があります。クエリが返す必要がある属性を特定し、それらの属性だけをインデックスに射影することで、書き込みコストは最小になります。

## ローカルセカンダリインデックスのストレージに関する考慮事項
<a name="LSI.StorageConsiderations"></a>

アプリケーションがテーブルに項目を書き込むと、DynamoDB では正しい属性のサブセットが、それらの属性が表示されるローカルセカンダリインデックスに自動的にコピーされます。AWS アカウントでは、テーブル内の項目のストレージと、そのベーステーブルのローカルセカンダリインデックスにある属性のストレージに対して課金されます。

インデックス項目が使用するスペースの量は、次の量の合計になります。
+ ベーステーブルのプライマリキー (パーティションキーとソートキー) のサイズのバイト数
+ インデックスキー属性のサイズのバイト数
+ 射影された属性（存在する場合）のサイズのバイト数
+ インデックス項目あたり 100 バイトのオーバーヘッド

ローカルセカンダリインデックスに必要なストレージは、インデックス内の 1 項目の平均サイズの見積もり値に、インデックス内の項目数を掛けて見積もることができます。

特定の属性が定義されていない項目がテーブルに含まれており、その属性がインデックスソートキーとして定義されている場合、DynamoDB はその項目に関連するデータをインデックスに書き込みません。

## ローカルセカンダリインデックス内の項目コレクション
<a name="LSI.ItemCollections"></a>

**注記**  
このセクションは、ローカルセカンダリインデックスがあるテーブルだけに関係します。

DynamoDB において、*項目コレクション*とは、テーブルおよびそのローカルセカンダリインデックス全体で同じパーティションキーの値を持つ項目のグループです。このセクションで使用する例では、`Thread` テーブルのパーティションキーは `ForumName` で、`LastPostIndex` のパーティションキーも `ForumName` です。同じ `ForumName` を持つテーブルとインデックス項目は、すべて同じ項目コレクションの一部です。例えば、`Thread` テーブルと `LastPostIndex` ローカルセカンダリインデックスには、フォーラム `EC2` 用の項目コレクションと、フォーラム `RDS` 用の別の項目コレクションがあります。

次の図は、フォーラム `S3` の項目コレクションを示しています。

![テーブル、および同じパーティションキー値 S3 を持つローカルセカンダリインデックスを含む DynamoDB 項目のコレクション。　](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/LSI_04.png)


この図では、項目コレクションは、`Thread` および `LastPostIndex` 内のすべての項目で構成されていて、`ForumName` パーティションキーの値は「S3」です。テーブルにその他のローカルセカンダリインデックスがあった場合には、`ForumName` が「S3」であるそれらのインデックス内の項目も、項目コレクションの一部になります。

DynamoDB では次のオペレーションのいずれかを使用して、項目コレクションに関する情報を返すことができます。
+ `BatchWriteItem`
+ `DeleteItem`
+ `PutItem`
+ `UpdateItem`
+ `TransactWriteItems`

これらのオペレーションでは、それぞれ `ReturnItemCollectionMetrics` パラメータがサポートされています。このパラメータを `SIZE` に設定すると、インデックス内の各項目コレクションのサイズに関する情報が表示されます。

**Example**  
以下に、`UpdateItem` が `Thread` に設定されている、`ReturnItemCollectionMetrics` テーブルでの `SIZE` オペレーションの出力の例を示します。更新された項目には `ForumName` 値「EC2」があったため、出力にはその項目コレクションに関する情報が含まれています。  

```
{
    ItemCollectionMetrics: {
        ItemCollectionKey: {
            ForumName: "EC2"
        },
        SizeEstimateRangeGB: [0.0, 1.0]
    }
}
```
`SizeEstimateRangeGB` オブジェクトは、この項目コレクションのサイズが 0 GB と 1 GB の間であることを示します。DynamoDB では、このサイズ見積りが定期的に更新されるため、項目を変更した時には次回の数字が異なる場合があります。

### 項目コレクションのサイズ制限
<a name="LSI.ItemCollections.SizeLimit"></a>

1 つ以上のローカルセカンダリインデックスを含む項目コレクションのサイズは、すべて最大 10 GB です。これは、ローカルセカンダリインデックスのないテーブルの項目コレクションには適用されません。また、グローバルセカンダリインデックスの項目コレクションにも適用されません。1 つ以上のローカルセカンダリインデックスを含むテーブルのみに影響します。

項目コレクションが 10 GB の制限を超えると、DynamoDB は `ItemCollectionSizeLimitExceededException` を返す可能性があります。この場合、その項目コレクションに項目を追加したり、項目サイズを大きくしたりすることができなくなる場合があります。（項目コレクションのサイズを小さくする読み込み/書き込みオペレーションは、引き続き実行できます)。その他の項目コレクションには項目を追加することができます。

項目コレクションのサイズを小さくするには、次のいずれかを実行します。
+ 問題になっているパーティションキーの値を持つ不要な項目を削除します。ベーステーブルからこれらの項目を削除すると、DynamoDB では同じパーティションキーの値を持つインデックスエントリも削除されます。
+ 属性を削除するか属性のサイズを小さくすることで、項目を更新します。これらの属性がローカルセカンダリインデックスに射影されている場合には、DynamoDB では対応するインデックスエントリのサイズも小さくなります。
+ 同じパーティションキーおよびソートキーを使用して新しいテーブルを作成し、古いテーブルから新しいテーブルに項目を移動します。これは、頻繁にアクセスされない履歴データがテーブルに含まれている場合に適した方法です。また、この履歴データを Amazon Simple Storage Service (Amazon S3) にアーカイブすることを検討することもできます。

項目コレクションの合計サイズが 10 GB 未満になると、再び同じパーティションキーの値を使用して項目を追加できます。

項目コレクションのサイズを監視するようにアプリケーションを設定することをお勧めします。1 つの方法としては、`ReturnItemCollectionMetrics`、`SIZE`、`BatchWriteItem`、または `DeleteItem` を使用する場合に、`PutItem` パラメータを `UpdateItem` に設定するというものがあります。アプリケーションで出力内の `ReturnItemCollectionMetrics` オブジェクトを調査し、項目コレクションがユーザー定義の制限（たとえば 8 GB）を超えた場合にエラーメッセージを記録するようにします。制限を 10 GB より低く設定すれば早期警告システムになり、項目コレクションが上限に達する前に余裕をもって何らかの対処をとることができます。

### 項目コレクションおよびパーティション
<a name="LSI.ItemCollections.OnePartition"></a>

1 つ以上のローカルセカンダリインデックスを含むテーブルでは、各項目コレクションは 1 つのパーティションに保存されます。このような項目コレクションの合計サイズは、そのパーティションのキャパシティー (10 GB) に制限されます。データモデルにサイズに制限のない項目コレクションが含まれている場合や、一部の項目コレクションが将来に 10 GB を超えると合理的に予期されるアプリケーションでは、代わりにグローバルセカンダリインデックスの使用を検討します。

アプリケーションを設計する場合は、テーブルデータが異なるパーティションキー値に均一に分配されるようにする必要があります。ローカルセカンダリインデックス を持つテーブルについては、単一のパーティション内の単一の項目コレクションに読み込み/書き込みアクティビティの「ホットスポット」が作られないように、アプリケーションを設計します。