導入
「AWS中級者を目指すための」と題して、AWSの各サービスについての深掘りをしていく記事です。
これらの記事では、自分が業務をしている際や勉強をしている際に疑問に感じたことを解消し、表面的にしかわかっていないところから一歩ステップアップするための記事となっています。
対象読者
- Amazon DynamoDBについてざっくりわかっている方
- DynamoDBの利用シーンや、設計観点の理解が不安な方
- プライマリキーやセカンダリインデックスのことについて理解が不安な方
そのため、この記事を通して、Amazon DynamoDBについて知ってもらうことで、同様のモヤモヤを抱えている方の一助になればと考えています。
この記事を作成するに際して感じていた課題
- DynamoDBがパフォーマンスが高く高速ということは知っているが、その仕組みを理解できていない
- キー構造やインデックスについて理解が浅い
この記事で解決したいこと
DynamoDBのキー構造やインデックスについて理解するとともに、どうやって高速に処理しているかも理解する
Amazon DynamoDBのキー構造
プライマリキー
DynamoDB ではテーブル作成時にプライマリキーの構成を以下のどちらにするか選択します。
- 1つのキー (パーティションキー) のみをプライマリキーにするテーブル
- 2つのキーの組み合わせ (パーティションキーとソートキー) をプライマリキーにするテーブル
パーティションキー
前提として、DynamoDBでは、データが増大し、スループット要件が高まるにつれて、パーティションの数を自動的に増やし、分散してデータが保存されます。
DynamoDBでは、保存の際、パーティションキーの値をハッシュしてパーティションを決定します。
そのため、GetItemでは、O(1)で高速アクセス可能となります。
DynamoDB の制約:
- 1つのパーティションキー値につき最大 10GB
- 平均的なアイテムサイズが 1KB なら約 10,000 アイテム
パーティション内検索:
log₂(10,000) ≈ 13〜14回の比較
実用上は「ほぼ一定」と見なせる
パーティションキー + ソートキー
ソートキーを持つ場合、同じパーティションキー値を持つすべての項目は、ソートキー値でソートされてまとめて保存されます。
ソートキーによって各パーティション内で インデックス が生成され、範囲(レンジ)指定した検索ができます。(Query)
GetItemの計算量については、パーティションキーの考えと同様となります。
Queryの際はPKで場所を絞り、SK順に連続した k件を読み取るだけなので、O(logk)となります。
セカンダリインデックス
Amazon DynamoDBでは、プライマリキーの値を指定して、テーブルの項目に高速アクセスすることが可能になります。しかし多くのアプリケーションでは、プライマリキー以外の属性を使って、データに効率的にアクセスできるようにセカンダリ(または代替)キーを 1 つ以上設定することで、メリットが得られることがあります。
LSI(ローカルセカンダリインデックス)
パーティションキーはベーステーブルと同じで、ソートキーが異なるインデックス。ローカルセカンダリインデックスは、ローカルセカンダリインデックスのすべてのパーティションの範囲が同じパーティションキーバリューを持つベーステーブルのパーティションに限定されるという意味で「ローカル」です。
後から変更することは不可
GSI(グローバルセカンダリインデックス)
パーティションキーおよびソートキーを持つインデックス。ベーステーブルのものとは異なる場合があります。このインデックスに関するクエリがすべてのパーティションにまたがり、ベーステーブル内のすべてのデータを対象とする可能性があるため、グローバルセカンダリインデックスは「グローバル」と見なされます。グローバルセカンダリインデックスは、ベーステーブルとは別に独自のパーティション領域に保存され、ベーステーブルとは別にスケーリングします。
後から追加することが可能
疑問1
Q.
DynamoDBでは、プライマリキーでのアクセス以外ではフルスキャンが発生するから、事前にアクセスパターンを決めておく必要があるとよく聞くが、GSIの仕組みがあるなら、事前にアクセスパターンを想定しておく必要がないのではないか?
A.
GSIを1つ貼ると、ストレージのコストがテーブル1つ分増加します。また、データの書き込み時にもGSI用のテーブルを更新する必要が発生し、テーブルに貼るGSIの分だけ、ストレージコストや書き込みコストが増加します。
疑問2
Q.
GSIで変更するパーティションキー、ソートキーってそもそも一意であることが保証されている必要があるのか。
A.
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html
参考
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/SecondaryIndexes.html
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/HowItWorks.Partitions.html
