dynamoDB基礎 自分用メモ

ざっくり

awsのkvs。
高速なパフォーマンスとシームレスな拡張性がウリ。スケーリングとかをよしなにやってくれる。
超大量のデータをSQLに格納するのはとてもしんどい。そんなときに高速に読み書きを行うことができ圧倒的なスケーリングをすることができるdynamoDBが輝く。

1秒あたり数万もしくは数百万のr/wが必要な場合とかに。

ただしSQLに比べ複雑な読み込みができない(できてもそういったケースはそもそもdynamoDBが適していない)。

可能な読み込みは以下の3種類

  • GetItem:  テーブルからプライマリキーを指定して1つのitemを取り出す。
    直接必要なものにアクセスするので一番効率的。
    必要なAtrributeを取り込むことができる。

  • Query : パーティションキー(後述)を使用して特定の項目を取り出すことができる。
    ソートキーが存在する場合、これを条件としデータの一部のみを取得することができる。
    データが格納されている物理的なストレージを指定するため高速かつ効率的にアクセスすることができる

  • Scan : 指定されたテーブルですべての項目を取り出す。
    大量のシステムリソースを消費するため大きなテーブルでは非推奨

  • ExecuteStatement : SQL互換の PartiQL が使用でき、テーブルから一つまたは複数の項目を取得することができる。

上から順に非効率的になっていく。基本的には日常的な読み込みはQueryまででこなしたい。 batch系はbatchGetItemやらBatchWriteItemあるがいったんここでは除外

固有名詞

名前 説明
Table rdbのTableとかと一緒。dynamoDBはデータをtableに保存し、他のrdbのようにその上に database といったものは存在しない。
(するかも知れないがユーザは触ることができない/意識する必要がない)
Item rdbでいうレコード。
Itemをそれぞれ一意に識別するプライマリキーが存在する。このプライマリキーが沼。
プライマリキー以外は必須な要素は存在しない。また、Tableに保存できるItemの数に制限は存在しない。
Attribute rdsでいうカラム。Itemは1つ以上のAttributeで構成される。
パーティションキー 特殊なAttribute。スキーマレスなdynamoDBにおいて唯一必須なAttribute。別名hash key。
コレ単体でItemを一意に識別できる場合、単体でプライマリキーになる。
そうじゃない場合、ソートキーと組み合わせることによってプライマリキーになる。
どのパーティション(DynamoDB 内部の物理ストレージ)に保存するかをこのAttributeにより指定する。
ソートキー 特殊なAttribute。別名range key。dynamoDBを難解にする原因その1。
Table内でパーティションキーだけてItemを一意に識別できない場合、使用される。
パーティションキーとソートキーの組み合わせでItemを一意に識別できることが求められるので、それ相応の内容になる。
単純にパーティションキーと別のAttributeだけの組み合わせで一意に識別することができない場合、
attribute1#attribute2
みたいな形のソートキーにして、PKとSKの組み合わせて一意を取りに行くケースが多い。
ローカルセカンダリインデックス dynamoDBを難解にする原因その2。
テーブル作成時にしか作成することができないindex。強整合性を持ち、インデックスに射影されていないAttributeも取りに行く事ができる。
テーブル作成時にしか作成することができず、且つローカルセカンダリインデックスが原因で一部容量が制限されるので
どうしても強整合性が必要といったケースでも無い限りは、公式にGSIを使用することを推奨されている。
グローバルセカンダリインデックス dynamoDBを難解にする原因その3。
任意のタイミングで作成/削除ができるが結果整合性しか持たずインデックスに射影されていないAttributeを取得することができないインデックス。

また、以前はパーティションキー、ソートキーがそれぞれハッシュキー、レンジキーと言う名前で使われていた。
terraformとかcfnではその名前で使われていたり

The partition key of an item is also known as its hash attribute. The term hash attribute derives from the use of an internal hash function in DynamoDB that evenly distributes data items across partitions, based on their partition key values.

The sort key of an item is also known as its range attribute. The term range attribute derives from the way DynamoDB stores items with the same partition key physically close together, in sorted order by the sort key value.

docs.aws.amazon.com


キー、インデックス

スキーマレスなので、itemを追加する際に全てのAttributesを網羅する必要は無いが、Itemを一意に識別するプライマリキーを設計する必要がある。

パーティションキー自体が一意であれば単体でプライマリキーとなる。
パーティションキーで一意ではないのであれば、パーティションキーソートキー2つのキーを合わせてプライマリキーとなる。*

dynamoDBでは内部的にはitemをパーティション(DynamoDB 内部の物理ストレージ) ごとに分けて格納する。*
その際にソートキーも存在すれば、同じパーティションキーを持つItemは全て同じパーティション内に、ソートキーを元にソートされた状態で格納される。

パーティションキー

どの物理パーティションに格納されるかを決めるkeyであり、書き込まれるデータは全てのパーティションに分散され均一に格納されることが望ましい。
一般的なパーティションキースキーマのプロビジョニングされたスループット効率の比較表は以下。

パーティションキーバリュー 均一性
ユーザー ID (アプリケーションに多くのユーザーが存在する場合) 良好
ステータスコード (可能性のあるステータスコードが少しだけある場合) 不良
項目の作成日。直近の期間 (日、時、分など) に切り上げられます。 不良
バイス ID (各デバイスが比較的類似した間隔でデータにアクセスする場合)。 良好
バイス ID (追跡中のデバイスが多数あり、そのうちの 1 つのデバイスが他のすべてのデバイスよりも頻繁に使用される場合) 不良

docs.aws.amazon.com

いい感じに分割しない場合、局所的に頻繁にアクセスされる「ホット」パーティションが発生してしまう。
これにより、スロットリングが発生することや、プロビジョニングされた I/O 容量を効率的に使用されないことがある。

アクセス頻度の多いItemが同一パーティションに存在しないように、パーティションのバランスが再調整される。*このあたりはアダプティブ容量とかプロビジョニング周りの話なので一旦スルー

ソートキー

パーティションキーと組み合わせて一意に識別できるように設定されるキー。

設計が優れたソートキーには、2 つの主な利点があります。

関連情報を 1 つの場所にまとめて、効率的にクエリを実行することができます。ソートキーを慎重に設計することで、begins_with、between、>、< などの演算子による範囲のクエリを使用して、一般的に必要な関連項目のグループを検索することができます。

複合ソートキーを作成すれば、データの階層的 (1 対多) な関係を定義して、任意の階層レベルでクエリを実行することができます。

例えば、地理的場所を示すテーブルでは、次のようにソートキーを構成できます。

[country]#[region]#[state]#[county]#[city]#[neighborhood]

これにより、これらの集計レベルのいずれかの場所のリスト (country から neighborhood、またその間にあるすべてのもの) に対して、範囲のクエリを効率的に行うことができます。 docs.aws.amazon.com

ローカルセカンダリインデックス LSI

dynamoDBのインデックスの一つ。テーブルを作成する際に定義する必要があり、追加での作成はできない。
インデックスのパーティションキーはテーブルのパーティションキーと同じである必要がある。ただし、ソートキーは任意の値で可。

ローカルセカンダリインデックスの全てのパーティションの範囲が同じパーティションキーバリューを持つベーステーブルのパーティションに限定されるという意味で「ローカル」である。
テーブル及びテーブルのLSI全体において同一のパーティションキーを持つItem(Attribute Colection)は合計で10GBを超えることができない(上限緩和申請とかも不可能)。
スループット設定はベーステーブルと共有であり、最大で5個のLSIが作成可能。

また、パーティションキーで指定された1つのパーティションに対してのみにしかクエリを実行することができない。
が、インデックスに射影されていないAttributeもリクエストすることができる。

せっかくの容量無制限DBにもかかわらずAttribute Colectionで容量の制限が発生してしまったり、後々その制限に引っかかってしまった場合データの分割や削除、定常的に制限を超えないための監視、果てはモデリングのし直しまで必要になってしまうケースが有る。
よって、一般的にはLSIではなく、後述のGSIを使用することが推奨されるが、例外としてクエリ結果に強整合性が必要な場合、こちらを私用する必要がある。GSIでは結果整合性しかサポートしない。

docs.aws.amazon.com

グローバルセカンダリインデックス GSI

dynamoDBのもう一つのインデックス。
いつでも追加作成/削除を行うことができ、作成数はデフォルトのクォータで20個作成することができる(とはいってもindexだし必要最低限数であることに越したことはないが)。
パーティションキーソートキーともにホストテーブルの任意のAttributeを使用することができ、それ以外のattributeも任意に選択することができる。

ただし、インデックスに射影されていないAttributeを取得することはできない。

アプリケーションが非キー属性に頻繁にアクセスする場合は、それらの属性をGSIに射影することが推奨されている。GSIに射影したことによるコストの増加は頻繁に(非キー属性を取得するための)テーブルスキャンコストの減少により相殺され、且つクエリが早くなるケースが多いため。

ただし、GSIでは結果整合性しか担保されていない。

ここまでが基礎 多対多のdb設計

docs.aws.amazon.com

youtu.be