これら2つのセカンダリインデックスとそれらの違いに興味があります。これがどのように見えるか想像するのは難しいです。そして、これは私よりも多くの人々に役立つと思います。
ローカルセカンダリインデックスはまだ元のハッシュキーに依存しています。ハッシュ+範囲を持つテーブルを提供する場合、LSIをハッシュ+範囲1、ハッシュ+範囲2 ..ハッシュ+範囲6と考えてください。さらに5つの範囲属性を取得して照会できます。また、プロビジョニングされたスループットは1つだけです。
グローバルセカンダリインデックスは、新しいパラダイム-インデックスごとに異なるハッシュ/範囲キーを定義します。
これにより、テーブルごとに1つのハッシュキーが使用されていました。これは、GSIを定義する際に、インデックスごとにプロビジョニングされたスループットを追加し、それを支払う必要がある理由でもあります。
相違点に関する詳細情報は GSIアナウンスメント にあります。
ドキュメントからの正式な定義は次のとおりです。
グローバルセカンダリインデックス—テーブル上のものとは異なるハッシュキーとレンジキーを持つインデックス。グローバルセカンダリインデックスは、インデックスのクエリがすべてのパーティションにわたってテーブル内のすべてのデータにまたがることができるため、「グローバル」と見なされます。
ローカルセカンダリインデックス—テーブルと同じハッシュキーを持つが、範囲キーが異なるインデックス。ローカルセカンダリインデックスは、ローカルセカンダリインデックスのすべてのパーティションが同じハッシュキーを持つテーブルパーティションにスコープされるという意味で「ローカル」です。
ただし、違いは主要な定義の点で可能性をはるかに超えています。インデックスを維持するためのコストと労力に直接影響を与えるいくつかの重要な要因を以下に示します。
ローカルセカンダリインデックスは、テーブルのスループットを消費します。ローカルインデックスを介してレコードをクエリすると、操作はテーブルの読み取りキャパシティーユニットを消費します。ローカルインデックスを持つテーブルで書き込み操作(作成、更新、削除)を実行すると、2つの書き込み操作が行われます。1つはテーブル用、もう1つはインデックス用です。両方の操作で、テーブルの書き込み容量ユニットが消費されます。
グローバルセカンダリインデックスには独自のプロビジョニングされたスループットがあります。インデックスをクエリすると、操作はインデックスからの読み取り容量を消費します。グローバルインデックスを持つテーブルで書き込み操作(作成、更新、削除)を実行すると、書き込み操作、1つはテーブル用、もう1つはインデックス用*。
*グローバルセカンダリインデックスのプロビジョニングされたスループットを定義するときは、次の要件に特に注意を払ってください。
テーブルの書き込みを成功させるには、テーブルとそのすべてのグローバルセカンダリインデックスのプロビジョニングされたスループット設定に、書き込みに対応するための十分な書き込み容量が必要です。そうしないと、テーブルへの書き込みが抑制されます。
ローカルセカンダリインデックスは、テーブルを作成するときにのみ作成できます。ローカルセカンダリインデックスを既存のテーブルに追加する方法はありません。また、インデックスを作成すると削除できません。
グローバルセカンダリインデックスは、テーブルを作成して既存のテーブルに追加するときに作成できます。既存のグローバルセカンダリインデックスを削除することもできます。
ローカルセカンダリインデックスは結果整合性または強い整合性をサポートしますが、グローバルセカンダリインデックスは結果整合性のみをサポートします。
ローカルセカンダリインデックスを使用すると、インデックスに投影されない属性を取得できます(ただし、パフォーマンスと消費される容量単位の追加コストがかかります)。グローバルセカンダリインデックスを使用すると、インデックスに投影された属性のみを取得できます。
セカンダリインデックスに定義されたキーの一意性に関する特別な考慮事項:
ローカルセカンダリインデックスでは、範囲キー値は特定のハッシュキー値に対して一意である必要はありません。同じことがグローバルセカンダリインデックスに適用され、キー値(ハッシュおよび範囲)は一意である必要はありません。
ソース: http://docs.aws.Amazon.com/amazondynamodb/latest/developerguide/SecondaryIndexes.html
これらはインデックスによる可能な検索です:
テーブルのハッシュおよび範囲インデックス:これらは、以前のバージョンのAmazon AWS SDKの通常のインデックスです。
グローバルインデックスとローカルインデックス:これらは、テーブルの既存のハッシュインデックスと範囲インデックスに加えて、テーブル上に作成された「追加の」インデックスです。 グローバルインデックスはハッシュに似ています。 Range indexは、テーブルのハッシュで使用される範囲インデックスと同様に動作します。コードのエンティティモデルでは、ゲッターに次のように注釈を付ける必要があります。
グローバルインデックスの場合:
@DynamoDBIndexHashKey(globalSecondaryIndexName = INDEX_GLOBAL_RANGE_US_TS)
@DynamoDBAttribute(attributeName = PROPERTY_USER)
public String getUser() {
return user;
}
グローバルインデックスに関連付けられた範囲インデックスの場合:
@DynamoDBIndexRangeKey(globalSecondaryIndexName = INDEX_GLOBAL_RANGE_US_TS)
@DynamoDBAttribute(attributeName = PROPERTY_TIMESTAMP)
public String getTimestamp() {
return timestamp;
}
また、グローバルインデックスによってテーブルを読み取る場合、それは最終的な読み取り(一貫性のない読み取り)である必要があります。
queryExpression.setConsistentRead(false);
配置方法の1つは次のとおりです。
LSI-複数の異なる属性を使用してクエリを「フィルタリング」または制限しながら、単一のハッシュキーでクエリを実行できます。
GSI-テーブル内の複数のハッシュキーでクエリを実行できますが、結果としてスループットが余分にかかります。
以下に、テーブルタイプとその機能の詳細な内訳を示します。
ハッシュのみ
おそらく既に知っているように。既に存在するハッシュキーに書き込むと既存のデータが上書きされるため、ハッシュキー自体は一意でなければなりません。
ハッシュ+範囲
ハッシュキーと範囲キーを使用すると、異なる範囲キーがある限り、同じ複数のハッシュキーを使用できます。この場合、既に存在するハッシュキーに書き込むが、そのハッシュキーでまだ使用されていない範囲キーを使用すると、新しいアイテムが作成されますが、同じハッシュ+範囲の組み合わせを持つアイテムの場合すでに存在する場合、一致するアイテムを上書きします。
これを考える別の方法は、フォーマットのあるファイルのようなものです。ファイルの形式(範囲)が異なる限り、同じフォルダー(テーブル)内に同じ名前(ハッシュ)のファイルを作成できます。同様に、名前が異なる限り、同じ形式の複数のファイルを持つことができます。
LSI
LSIは基本的にハッシュキー+範囲キーと同じであり、アイテムを作成するときも同じ規則に従いますが、LSIにも値を指定する必要があります。空/ヌルのままにすることはできません。
LSIが「Range-Key 2」であると言うことは、file.format.lsi
およびfile.format.lsi2
という名前のファイルを(以前のファイルと形式を使用して)持つことができないため、完全に正しいとは限りません。ただし、file.format.lsi
とfile.format2.lsi
またはfile.format.lsi
とfile2.format.lsi
を使用できます。
基本的に、LSIは単なる「フィルターキー」であり、実際の範囲キーではありません。ベースハッシュと範囲の値の組み合わせは一意である必要がありますが、LSIの値は一意である必要はありません。それを見るより簡単な方法は、ファイル内のデータとしてLSIを考えることかもしれません。 fileFormat
に関係なく、「PROJECT101」という名前のすべてのファイルを検索し、内部のデータを読み取って、クエリに含めるものと省略するものを決定するコードを作成できます。これは基本的にLSIの動作方法です(ファイルを開いてその内容を読み取る余分なオーバーヘッドはありません)。
GSI
GSIの場合、基本的にはGSIごとに別のテーブルを作成しますが、それらの間でデータをミラーリングする複数の個別のテーブルを維持する手間がありません。そのため、スループットが高くなります。
したがって、GSIの場合、ベースハッシュキーとしてfileName
を指定し、ベースレンジキーとしてfileFormat
を指定できます。次に、fileName2
のハッシュキーとfileFormat2
の範囲キーを持つGSIを指定できます。 fileName
でのみクエリできるLSIとは異なり、必要に応じてfileName
またはfileName2
でクエリを実行できます。
主な利点は、2つではなく1つのテーブルを維持するだけでよく、プライマリハッシュ/範囲またはGSIハッシュ/範囲のいずれかに書き込むと、他のテーブルも自動的に更新されることです。そのため、マルチテーブル設定でできるように、他のテーブルを更新することを「忘れる」ことはできません。また、マルチテーブルセットアップの場合のように、一方を更新した後、他方を更新する前に接続が失われる可能性はありません。
さらに、GSIはベースハッシュ/範囲の組み合わせを「オーバーラップ」できます。したがって、ベースハッシュ/範囲としてfileName
とfileFormat
を、GSIとしてfilePriority
とfileName
を使用してテーブルを作成することができます。
最後に、GSIのハッシュと範囲の組み合わせは一意である必要はありませんが、ベースのハッシュと範囲の組み合わせは一意である必要があります。これは、デュアル/マルチテーブルセットアップでは不可能ですが、GSIでは可能です。その結果、更新時にベースとGSIハッシュ+範囲の両方に値を提供する必要があります。これらの値はどれも空/ヌルにすることはできません。
別の説明方法:LSIは、同じハッシュキーを持つアイテムに対して追加のクエリを実行するのに役立ちます。 GSIは、「テーブル全体」のアイテムに対して同様のクエリを実行するのに役立ちます。とても便利です。
ユーザープロファイルテーブルがある場合:unique-id、name、email。ここで、名前、電子メールでテーブルをクエリ可能にする必要がある場合、唯一の方法はそれらをGSIにすることです(LSIは助けません)
このドキュメントはかなり良い説明を提供します:
https://aws.Amazon.com/blogs/aws/now-available-global-secondary-indexes-for-Amazon-dynamodb/
私はこの質問にコメントできませんでしたが、書き込みと読み取りのパフォーマンスの点では優れています:
(テーブルの読み取り/書き込みスループットが100のローカルインデックス)または(読み取り/書き込みスループットが50のグローバルインデックスと、テーブルの読み取り/書き込みスループットが50の場合?)
ユースケースに個別のパーティションキーは必要ありません。したがって、必要な機能にはローカルインデックスで十分です。