DynamoDBのキーとインデックスについて

DynamoDBのキーとインデックスがずっと覚えられないので個人メモです。
「自分が何となくイメージできること」を目的としているため、正確性に欠ける表現がある可能性があります。



# 1.DynamoDBで登場するキー

- プライマリキー
  - パーティションキー（旧ハッシュキー）
  - ソートキー（旧レンジキー）
- セカンダリインデックス 
  - ローカルセカンダリインデックス（LSI）
  - グローバルセカンダリインデックス（GSI）

# 2.予備知識
DynamoDBでは大量データを高速処理するため、パーティショニングによる分散処理を行っている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/e59b80b1-8f46-552c-84ef-57d5a9765b1d.png)

# 3.プライマリキー
データを一意にするため、DynamoDBでテーブル作成時に **プライマリキー** を決定しておく必要がある。

 **プライマリキー** のパターン

- パーティションキーのみでプライマリキーとするパターン
- パーティションキーとソートキーのセットでプライマリキーとするパターン

以下テーブルを例に考える。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/3ea657d2-90a0-049c-9ddb-fbdd90124a21.png)

## 3-1.パーティションキーのみでプライマリキーとするパターン
「テーブル名：名簿」で「ID」は行ごとに一意となるためこれだけでパーティションキーになる。
パーティションを指定した検索ができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/32664bfa-0768-8bb5-95c0-67e325f9f76f.png)
DynamoDBのデータは複数のパーティションに分散して保存される。
DynamoDBはパーティションキーの値をハッシュして保存先のパーティションを決定する。このためパーティションキーは昔はハッシュキーと呼ばれていた。

## 3-2.パーティションキーとソートキーのセットでプライマリキーとするパターン
「テーブル名：兼業含む名簿」の場合、「ID」をパーティションキー、「Job」をソートキーとすることで行を一意にできる。
ソートキーによって各パーティション内で **インデックス** が生成され、範囲（レンジ）指定した検索ができる。このため昔はソートキーをレンジキーと呼んでいた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/af4d53bb-0167-4522-06bb-d4ced2bd2967.png)
パーティションキーによってパーティションが分けられるのは「3-1.パーティションキーのみでプライマリキーとするパターン」と同じ。

 **テーブル名、パーティションキー、ソートキーはテーブル作成時にしか指定できない。テーブル作成後の変更はできない。** 

# 4.セカンダリインデックス
プライマリキーが一つ目のインデックス、つまりプライマリインデックスなのに対し、セカンダリインデックスは二つ目以降のインデックスとして使用する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/40bcf2c8-2e1c-b454-7cd5-8f99e5a906a9.png)
パーティションキーとソートキーを設定しているテーブルでは、パーティションで絞り込んでソートキーで範囲指定することでクエリ検索ができる。ほかの属性はクエリ検索のキーに使用することができない。
誕生年月日や身長、体重で検索したい場合などに、セカンダリインデックスを設定することができる。

## 4-1.ローカルセカンダリインデックス（LSI）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/7ea08e42-db65-d43f-58aa-a07ddc6c86d0.png)
ソートキーとは違う別のインデックスを作成する。
上の図では身長（height）をローカルセカンダリインデックスに設定している。
プロビジョニング済キャパシティモードの場合、テーブルの読み込みキャパシティユニット・書き込みキャパシティユニットを使用する。

 **ローカルセカンダリインデックスはテーブル作成時にしか作成できない。あとから追加できない。** 

## 4-2.グローバルセカンダリインデックス（GSI）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1723719/8588c980-da9c-7f52-f387-fbe96606d158.png)
テーブルのパーティションキーと無関係の属性でクエリ検索したい場合グローバルセカンダリインデックスを使用する。
プライマリキーのパーティションキーとソートキーのセットとは別に、グローバルセカンダリインデックスとしてパーティションキーとソートキーのセットをプライマリキーに設定して検索できる。
上の図では身長（height）をパーティションキー、体重（weight）をソートキーとしたグローバルセカンダリインデックスを作成している。
テーブルとは違う構成でパーティションを分けるため、テーブルのリードレプリカを作成し、パーティションを新たに構成する。
プロビジョニング済キャパシティモードの場合、テーブルとは別に読み込みキャパシティユニット・書き込みキャパシティユニットを使用するため課金が増大する。

 **グローバルセカンダリインデックスはテーブル作成後、後から作成できる。** 

# 参考

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/HowItWorks.Partitions.html

https://www.amazon.co.jp/%E3%83%9D%E3%82%B1%E3%83%83%E3%83%88%E3%82%B9%E3%82%BF%E3%83%87%E3%82%A3-AWS%E8%AA%8D%E5%AE%9A-%E3%83%87%E3%83%99%E3%83%AD%E3%83%83%E3%83%91%E3%83%BC%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88%E8%A9%A6%E9%A8%93%E3%83%9D%E3%82%B1%E3%83%83%E3%83%88%E3%82%B9%E3%82%BF%E3%83%87%E3%82%A3-%E5%B1%B1%E4%B8%8B%E5%85%89%E6%B4%8B/dp/4798063401

https://www.udemy.com/course/aws-associate/

https://qiita.com/nomico/items/ce3f7bf5d6c95e843743