0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DynamoDBとは

Posted at

今回は以下の公式Youtubeを視聴し、まとめてみました。
https://www.youtube.com/watch?v=5gkCFQZVz_Q
https://www.youtube.com/watch?v=Wd5gbLQ2a1E

DynamoDBとは、フルマネージドかつサーバレスのKey-Value型NoSQLデータベースを指し、MySQLとかPostgresなどのRDBとは違ってSQLを使用しない。

基礎知識

  • Table/Items
    スクリーンショット 2024-05-21 18.30.52.png
    まあこの辺りはRDBと似たような感じでItemsがレコードに該当する。

  • Attributes
    スクリーンショット 2024-05-21 18.31.47.png
    各項目は1つ以上の属性で構成される。これはRDBでいうカラムとか列に該当する。また、PrimaryKeyの設定が必要となる。

ここまでは、RDBと大差ないので割と理解しやすい。
そして、PrimaryKeyの種類には、PartitionKey(PK)SortKey(SK)がある。

PKで決められないItemsをSKと組み合わせて検索する訳だけど、これもRDBでいう複合主キーと同じだから難しくないね。

設計の重要な考え方

アクセスパターンからテーブルを設計する

1.テーブル名を決定する
2.Partion Keyの検討
カーディなりティを高くしてホットスポットとならないように注意する
3.Sort Keyの検討
KINDで複数スキーマを詰め込む
基本形はテーブル名@固有ID(@は区切り文字のため任意)
例えば、以下のようなUserテーブル構成が一つの例となる。
PKは一意となる値でなければいけないし、SKもPKとの複合キーとして一意となる必要があるためuuidなどを使用(以下は長くなるのでuuidではない)

PK SK Attributes...(自由)
userId:"1111" kind:"item@1111" name: "Yuta"
userId:"1111" kind:"item@1112" Lv: 99
userId:"1111" kind:"item@1113" Address:"Tokyo"
userId:"1112" kind:"item@1114" name:"Taro"
userId:"1112" kind:"item@1115" Lv: 12

4.必要な情報を属性として追加
5.Read/Writeそれぞれのスループットを決定
テーブルはできるだけ少なくする
似たような情報をまとめることでテーブルを統合しておくことが重要。
例えば、Userが好きな本と好きな食べ物を持つテーブルを作成するとした場合

  • PartitionKeyをuserId
  • SortKeyをbook_favoriteとfood_favoriteとする

すると以下のように、同じテーブルに統合されることとなる。

PK SK Attributes
user1 book_favorite
food_favorite

ただ、ここで疑問に思う人もいると思うが、これで好きな食べ物だけを取得したい場合どうするのかということ。
そのように特定のSKを使用したい場合はPbegin_withで検索をかければ特定の条件で絞り込むことができる。

begins_with(sk, "food_")

他にも以下のような検索ができる

1 2
= 等しい
<> 等しくない
< 小さい
<= 以下
> 大きい
>= 以上
>= 以上
SortedResults 結果を取得する際にソートキーを使用してデータをソート
Count クエリまたはスキャンの結果として、返されるアイテムの数を取得
begins_with(attribute, substr) 指定した属性が特定の文字列で始まるアイテムを検索
contains(attribute, operand) 指定した属性に特定の値が含まれているアイテムを検索
attribute_exists(attribute) 指定した属性が存在するアイテムを検索
attribute_not_exists(attribute) 指定した属性が存在しないアイテムを検索
attribute_type(attribute, type) 指定した属性が特定の型であるアイテムを検索
size(attribute) 指定した属性のサイズ(文字列の長さまたはリストの要素数)を検索

その他のIndex

Local Secondary Index(LSI)

  • 特定のパーティションキーに対して、異なるソートキーを使って効率的に絞り込み検索を行うために使用される
  • Sort key以外に絞り込み検索を行うkeyを持つことができる
  • Partition keyが同一で、他のattributesで検索のために利用
  • テーブル作成時に追加
  • 1テーブルに最大5個

PrimaryKeyとSortKey、例えばUserID(PK)とWeaponId(SK)があったとして、その二つの組み合わせて検索できるけど、例えば、SKとしてWeaponIdじゃなくて、例えばMemberIdをSKとして使いたい!ってこともあるよね。

だから、その時にPKと組み合わせて使えるようにLSIとして設定しておけばMemberIdもSKとして使えるってこと。つまり、第二のSKってことだ。

例えば以下のテーブルがあるとする。

{
  "UserId": "user123",
  "OrderId": "order789",
  "OrderDate": "2024-05-21",
  "Category": "Electronics"
}

パーティションキーはUserId、プライマリソートキーはOrderIdとした場合、LSIとしてOrderDateを追加することで、以下のように特定のユーザーの注文履歴を日付でソートして検索できるようになる。

{
  "TableName": "Orders",
  "IndexName": "OrderDateIndex",
  "KeyConditionExpression": "UserId = :userId",
  "ExpressionAttributeValues": {
    ":userId": { "S": "user123" }
  },
  "ScanIndexForward": false
}

Global Secondary Index(GSI)

  • テーブルの主キー(パーティションキーとソートキー)とは異なるキーを使用してインデックスを作成するための機能
  • テーブル作成後に追加
  • 1テーブルに最大20個

まあ、これもLSIと考え方のベクトルは同じで、PKとSKの組み合わせを変えて検索したい!って時に作成すれば、使えるってこと。これはN:Mの時とかにスイッチして使うのに有用かな?

まあ簡単に違いをまとめると以下の感じ
LSI: パーティションキーは変えず、ソートキーのみを追加して検索を拡張。
GSI: パーティションキーとソートキーの両方を変更して、別の観点からデータを検索。

せっかくだからちゃんと違いをまとめると

項目 Local Secondadry Index Global Secondary Index
パーティションキー(PK) テーブルのパーティションキーと同じ テーブルとは異なるパーティションキーを指定できる
ソートキー(SK) 異なるソートキーを指定できる 異なるソートキーを指定できる
作成タイミング テーブル作成時にのみ定義可能 テーブル作成時でも後からでも追加可能
用途 パーティションキーが同じデータセット内で異なるソートキーを使った検索を行いたい場合 テーブル全体を異なるパーティションキーとソートキーで検索したい場合
制約 1テーブルあたり最大5つのLSI 1テーブルあたり最大20のGSI

アトリビュートに使用可能なデータ型

  • String
  • Number
  • Binary
  • Boolean
  • Null
  • 多値データ型
    Set of String
    Set of Number
    Set of Binary
  • ドキュメントデータ型
    List型
    Map型

ただし、PKとSKの型には文字列、数値、またはバイナリのみ使用可能

キャパシティモード

  • プロビジョンドキャパシティモード
    Read/Writeが予測可能な場合に使用
    オンデマンドへの変更は1日1回まで
    設定キャパシティに基づいて課金+データストレージに対する課金
  • オンデマンドキャパシティモード
    Read/Writeが予測不可能な場合に使用
    リクエスト数に応じて課金+データストレージに対する課金

単価はプロビジョンの方が安い。しかもオンデマンドではスロットルが発生する可能性があるのでスパイクに対応してくれる訳ではない。

したがって、負荷テストなどである程度キャパシティユニットを予測し、プロビジョンで高く設定しておき、大体の傾向が分かれば設定値を変更するのが良いらしい。

また、プロビジョンはリザーブができたり、オートスケールができたりするので積極的に活用すること。

そのほか設定

TTL

Itemの有効期限を設定し、データベースから自動削除されるタイミングを定義可能
追加料金は不要
ただし、期限切れ後、即座に削除される訳ではなく48時間以内に削除されるため、読み取り時にはアプリ側でフィルタリングが必要

パフォーマンスチューニング

まず遅い理由として以下の2点
クエリに問題がある
基本DynamoDBで問題が起きることはないが、あえて上げるなら

  • 1アイテムのサイズが巨大
    1アイテム400kbという制限があるが、400kbでも頻繁にやり取りをする場合はよくない
  • Query取得で返す件数が多い
    1回のやり取りで1MBしか返せないためそれ以上の場合はページングを行い何度もQueryを実行する必要がある。回避方法としては、行で伸ばすのではなく横に列を伸ばしていく。
  • Scanは論外

実行回数が多すぎる
ただし、DynamoDBは取得のたびにHTTPリクエストが走るためどうしようもない。
あえて回避方法を挙げるなら以下の通り

  • BatchWrite/BatchGet
    一部失敗の可能性もあるのでそれにはアプリケーション側で対応が必要
  • TransactGet/TransactWrite
    AllorNothingにしたいなら素直にTransaction系を使用

検索を詳しくみてみる

Composite key

以下のテーブルであればOpponentとDateで検索可能
スクリーンショット 2024-05-21 23.33.33.png

しかし、例えば以下のようにStatusも一緒に確認したい!となった時にまずいことが起きる。
何がまずいかというと、ここで使用しているFILTERはまずPKとSKで取得した後にフィルターをするからである。

例えば、この組み合わせが大量に存在する場合、かなりコストがかかる。
スクリーンショット 2024-05-21 23.34.20.png

これを解消する1つのアプローチとしてComposite keyがある。
これは何かというと、今回の場合StatusDateを組み合わせてStatusDateを作成しておくことである。
スクリーンショット 2024-05-21 23.36.13.png

すると、以下のようになる。
スクリーンショット 2024-05-21 23.37.21.png

このようにすればBEGINS_WITHを使用して探索すればかなりローコストで実現可能となる。賢い。
スクリーンショット 2024-05-21 23.37.57.png

Sparse Indexes

特定Itemにしか設定していない項目にGSIを含めることでプライマリーキー、ソートキー以外のキーでデータ抽出を容易にしてくれるテクニックの1つ

例えば、以下のようにGame-scores-tableのAward属性にChampが1人だけ設定するとしよう。
この場合、真正面から検索しようとするとテーブル全体をスキャンし、AwardがChampに該当するitemを検索することとなるが、これでは非常に非効率となる。

ここで、Sparse Indexesの考え方を踏まえて、このAwardをGSIに設定する。
これにより、Award属性をインデックスを使用して効率的かつ高速に検索することが可能となる。

スクリーンショット 2024-05-22 22.27.27.png

2本目の動画については22分あたりから触らないと理解が深まらなそうなので、言語化はまだできなそう。
また触り始めてから理解を深めて追記していきます〜。

GSI OVERLOADING

Vertical Pertitioning

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?