Amazon DynamoDBの基本
専門用語と横文字の多いこと多いこと。
深いところまで書きません。
あくまで基礎的なメモだけです。
ここを見て余裕で分かる人は、公式ドキュメントを見るべし。https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Introduction.html
DynamoDBの概要
AWSが提供するサービスの一つ。
高い信頼性、スケーラビリティ、低レイテンシーで安定した性能をもった、NoSQLデータベースサービス。

- 管理不要で信頼性が高い
- プロビジョンドスループット
- ストレージの容量制限がない
スケーラビリティ
ソフトウェア、システムの拡張性、拡張可能性のこと。DynamoDBは機器拡張が簡単におこなえるということになる。
レイテンシー
遅延のこと。DynamoDBは後記のパーティション機能のおかげでデータが大量になっても遅延が発生しにくいようにしてくれる。
NoSQLデータベース
SQL言語を使わずにデータへ接続できるデータベースのこと。
Key-Value型データベースを指すこともある。
(Key-Valueストア等)
SQLServerやOracleなどのRDBMSではデータ同士で複数紐付いたりするが、
NoSQLではデータが独立していて、一意となっている。
例えるならば、RDBMSはEXCELのような表形式。
NoSQLはフォルダやファイルのような感じ。
同じフォルダ内に同じ名前のファイルは作成できない。
プロビジョンドスループット
テーブルごとにReadとWriteそれぞれに対し、必要な分だけスループットキャパシティ(データ転送能力の余力)を割り当てる仕組みのこと。
負荷状況に合わせて自動でバランス調整してくれます。
構成要素
RDBMSとの用語比較
DynamoDB | RDBMS |
テーブル(Table) | テーブル |
項目(Item) | レコード |
属性(Attribute) | カラム |
プライマリキー
テーブルの各項目を一意に識別するキーのこと。
DynamoDBでは2種類をサポートしている。
プライマリキー(1つの属性(パーティションキー)で構成)
複合プライマリキー(2つの属性(パーティションキーとソートキー)で構成)
パーティションキー
1 つの属性で構成されたシンプルなプライマリキー。
パーティションキーのみを含むテーブルでは、2つの項目が同じパーティションキー値を持つことはできない。
ソートキー
複合プライマリキーの場合、2つの属性で構成される。
最初の属性はパーティションキー、2番目の属性はソートキー。
パーティションキーとソートキーが存在するテーブルでは、同じパーティションキー値が 2つの項目に割り当てられることがある。(ただし、ソートキー値は2つの項目で異なる必要がある。)
ソートキー値で並べ替えられた順に、DynamoDBが同じパーティションキーを持つ項目同士を物理的に近くに保存する。
また、クエリによって返される項目のソート順を決定するためだけのものではなく、データ検索オプションを拡張する。

データの読み込み分類
テーブルから単一の項目取得
GetItem
テーブルから複数項目取得
Query(キーを条件に特定範囲内の検索)
Scan(テーブル全体を検索)
負荷が大きい
注意点
Query, Scanで取得可能な容量上限(1MB)がある。
上限を越えると、クエリ応答に「LastEvaluatedKey」がセットされる。
キーを使った検索
単独PKテーブルの場合は、プライマリキー(パーティションキー)指定による1件取得か、
Scanによる全件取得しかできない。
複合PKテーブルにはパーティション内にインデックスが作成されるため、
「パーティションキーを指定した上でのソートキーによる範囲を指定したクエリ検索」が可能。
このインデックスを便宜的にローカル・プライマリ・インデックス(LPI)と呼ぶ。
ローカルとは、各パーティション内に作成されていることを意味する。
この構成上、「パーティションキーを指定しないソートキーのみの検索」はできない。

セカンダリインデックス
プライマリキー以外の属性で、データにアクセスできるようにするには、
インデックスを最初に定義しておく必要があり、2種類サポートされている。
ローカルセカンダリインデックス(LSI)
グローバルセカンダリインデックス(GSI)
ローカルセカンダリインデックス(LSI)
LPIを踏襲した仕組み。
ソートキー以外にインデックスを作成でき、パーティションキーを指定した上でのインデックスを作成した属性のクエリ検索ができる。

グローバルセカンダリインデックス(GSI)
インデックス用に新たにパーティションキーとソートキーを指定して検索できる。
LSiと違って、物理パーティションに囚われない検索が可能。

図の場合、「statusがOKでnameがTで始まるユーザを検索する」といった検索が可能。
物理パーティションをまたいで検索が出来る事が分かる。
注意点
インデックス用のパーティションキーとソートキーは一意にならない可能性がある。
(DynamoDB側で一意制約をかけることができない。)
そのため、完全な一意制は担保されず、2件以上が検索の結果として帰ってくる場合がある。
また、GSIに指定した属性は存在しない(null)可能性もある。
つまりScanの結果、返される値については「属性が存在するitemの全件数」となる。
パーティション
上図の通りDynamoDBではパーティションといった形で、データが分割される。
どうして分割しているのかというと、
複数のパーティションに分散されることで物理的な性能を保持するため。
逆にいうと、分割されればされる程、性能が落ちる。
分割はテーブルに割り当てたキャパシティ値によって決まり、
ストレージ容量とスループットが大きくなるにつれてパーティションが増えていく。
深い内容になるので、詳細は下記リンクを参照。
概要に下記にまとめる。
partitionとprimary keyの関係について
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/HowItWorks.Partitions.html
partition分割時の挙動について
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/best-practices.html#GuidelinesForTables.Partitions
読み込み・書き込みキャパシティ
DynamoDBでは読み込みと書き込みのキャパシティをそれぞれユニットと呼ばれる単位で設定できる。
書き込みキャパシティ値(WCU):1秒間に最大1KBのデータを1回書き込める
読み込みキャパシティ値(RCU):1秒間に最大4KBのデータを2回読み込める
パーティションの仕様や分割
1つのパーティションについて下記がサポートされる。
最大3,000のRCU
最大1,000のWCU
例として、RCU 1,000、WCU 1,000で設定した場合、以下の通り。
(1,0003,000)+(1,0001,000)=1.333(繰り上げで2になる)
設定したキャパシティ値は1つのパーティションではサポートしきれないので、
各パーティションに均等に分散される。
上記の例だとパーティションは2つなので、
各パーティションのキャパシティ値は、RCU 500、WCU 500 になる。
また、キャパシティ変更によってもパーティション数は変更される。
例として、RCU 1,000、WCU 1,000 で設定したテーブルに対して、
WCU 2,000 に変更した場合、以下の通り。
(1,0003,000)+(2,0001,000)=2.333(繰り上げて3になる)
この場合、パーティション数が2から3にならないので注意。
既存のパーティションが全て分割されるので、4つになる。(22=4)
よって、各パーティションのキャパシティ値は、RCU 250、WCU 500 になる。
ちなみに、ストレージ容量によってもパーティション数は変更される。
1つのパーティションには約10GBのデータを保持できる。
10GBを超えると、そのパーティションのみ分割され、単純にパーティションが1つ増える。
パーティション数を減らす…
パーティション数は、キャパシティ値を小さくしても減らない。
例として、RCU 1,000、WCU 1,000 で設定したテーブル(パーティション数が2つ)に対して、
WCU 500 に変更した場合、以下の通り。
(1,0003,000)+(5001,000)=0.8333(繰り上げて1になる)
本来は1つのパーティションで済む値だが、パーティション数は減らない。
キャパシティ値は各パーティションに分散されるので、
各パーティションのキャパシティ値は、RCU 500、WCU 250 になる。
このテーブルの片方のパーティションのストレージ容量が10GBを超えた場合、さらにややこしくなる。
パーティションは3つになり、「RCU 500、WCU 250」のパーティションが分割されるので、
各パーティションのキャパシティは以下のようになる。
- RCU 500、WCU 250
- RCU 250、WCU 125
- RCU 250、WCU 125
各パーティションのキャパシティ値が大きく落ちることが分かる。
キャパシティ値を超えるリクエストはないが、エラーが発生するということも。
処理が均等に分散されれば問題ないので、
「テーブルのプライマリーキーをランダムかつ均一にリクエストされるような値に設定する」設計にすることが、
公式でも推奨されている。
他に色んな回避策はあるらしいが、そちらは状況に合わせて別途調査をするしかない。
参考リンク集
https://qiita.com/blackcat5016/items/c2af7d3d55093134bac3
https://techblog.recochoku.jp/5654
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/HowItWorks.Partitions.html
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/best-practices.html#GuidelinesForTables.Partitions
コメント