概要
要点をまとめる。
初心者向け or ブランク発生時の思い出し用。
各種呼称
RDBとの対応。
テーブル → テーブル
レコード → 項目(item)
カラム → 属性(attribute)
ちなみに、属性は主キーとなる属性以外、項目ごとに自由に設定できる。
※RDB感覚でいうと、レコード1のカラムは hoge1,hoge2 だけど、レコード2のカラムは moge1,moge2 みたいなことができる
主キー
パーティションキーとソートキーがある。
パーティションキーの設計時は↓に注意(公式記事)
テーブルの主キーのパーティションキー部分は、テーブルのデータが格納されている論理パーティションを決定します。これにより、基本的な物理パーティションに影響を及ぼします。テーブルのプロビジョニングされた I/O キャパシティーは、これらの物理パーティション間で均等に分割されます。そのため、I/O リクエストを均等に分散しないパーティションキー設計では、「ホット」パーティションが作成される場合があります。これにより、スロットリングが発生したり、プロビジョニングされた I/O キャパシティーを効率的に使用されないことがあります。
要は操作対象になるパーティションキーに偏りがでないようにしろということ。
公式記事には、「日付をパーティションキーにすると、今日のパーティションキーにアクセスが集中するよね」、っていうのが例として挙げられている。
パーティションキーのみ
重複するパーティションキーは登録できない(RDBの主キーと同じ)。
パーティションキー+ソートキー
「パーティションキー+ソートキー」の組み合わせで重複する値は登録できない(RDBの複合主キーと同じ)。
取得した結果はソートキーを使ってソートされる。
検索
スキャンとクエリがある。
基本はクエリを使う。スキャンは全検索になるので注意。
実行した際のscannedCount
に注目する。scannedCount
が多くてCount
が少ない検索は無駄が多い検索であると言える。
読み込みキャパシティーユニットの消費はscannedCount
分消費されているので注意が必要。
※フィルタを使って最終結果数だけ絞っても、フィルタ無し時と同じ量だけ消費している
(フィルタはあくまで取得した結果に対して最終的な絞り込みをしているだけ)
スキャン
全検索となり、フィルタを使って結果を絞ったとしても(フィルタに主キーを使ったとしても)内部的には全検索されている。
※scannedCount
が登録されている全項目数になる。
また、Segment
とTotalSegments
を指定することで、並列で1つのテーブルに対してスキャンが可能。
クエリ
主キーを使うことにより、全検索ではない検索をすることが可能になる。
scannedCount
が指定された主キーに紐づく項目数のみになる。
パーティションキーのみのテーブルの場合
パーティションキーを指定することになり、scannedCount
は1件のみになる。
「パーティションキー+ソートキー」の場合
パーティションキーのみ指定の場合、そのパーティションキーの項目数がscannedCount
になる。
パーティションキーとソートキーを両方指定した場合、両方にマッチする項目数がscannedCount
になる。
また、フィルタを使って属性値に対しての一致条件を追加設定することができる。
ただし、scannedCount
はフィルタを使っていない場合と同じになる。
※scannedCount
:100、Count
:1 みたいな感じになる。
実装時メモ
一度に取得できる容量に上限がある
スキャン、クエリに関わらず、1度に取得できる容量に上限があり(最大1MB)、LastEvaluatedKey
が返ってきた場合、続きを取得するのにLastEvaluatedKey
の値をExclusiveStartKey
に指定する必要があるので注意。
boto3的には、↓で結果を取得するとその辺を自動でやってくれる。※詳細な実装例は こちらのリンク
client = boto3.client('dynamodb')
paginator = client.get_paginator('query')
下記 より、フィルタ前の結果に対して1MB制限なので注意
1 回の Query オペレーションで、最大 1 MB のデータを取得できます。この制限は、結果への FilterExpression の適用前に適用されます。レスポンスに LastEvaluatedKey が存在し、Null 以外の場合、結果セットをページ分割する必要があります (Paginating Table Query Results を参照)。
消費したキャパシティーユニット数を知りたい
ReturnConsumedCapacity
を指定すること。
※公式 の、「Capacity Units Consumed by Query」項
インデックス
細かなGSI、LSIの違いは 公式 の比較表を参照。
ローカルセカンダリイデックス(LSI)
要は代替ソートキー。
テーブルを作成する時に指定可能。(テーブルごとに最大5つ)
必ず、ベーステーブルと同じパーティションキーを持つ。
※「ベーステーブルと同じパーティションキー+任意の属性」という形になる
同じパーティションキーの項目の合計サイズが10GBになる制限が発生するため注意。
グローバルセカンダリインデックス(GSI)
現パーティションキー、ソートキーとは別で、パーティションキー、ソートキーを追加できる。
キャパシティーユニットの消費がインデックス専用のものになる(LSIはベーステーブルと共通)。
書き込み時のキャパシティーユニットの消費の注意
公式に、下記の記載があることから、ベーステーブルを更新するとGSIの更新も行われるため、ベーステーブル、GSI両方の書き込みキャパシティーユニットを消費することが分かる(つまり、書き込みキャパシティーユニット分の料金が倍になるので注意)。
※読み込み時はGSIの読み込みキャパシティーユニットのみ消費
スロットリングを避けるため、グローバルセカンダリインデックスのプロビジョニングされた書き込みキャパシティーは、ベーステーブルの書き込みキャパシティーと同じかそれより大きい必要があります。これは、新しい更新ではベーステーブルとグローバルセカンダリインデックスの両方に書き込むためです。
トランザクション
最大25個までのアクションに対して、全て問題なく実行できた場合(全部評価OK)は全てを有効にし、失敗した場合(評価NG)は全部なかった事にする、を制御するための機能になる。
ので、RDB感覚でcommit、rollbackができるわけではないので注意。
※例えば、DynamoDBとは全然関係ない処理に失敗したからrollbackする、っていうのは無理
TTL(Time To Live)
項目の有効期限を決めて自動で削除されるようにすることができる。
※ただし、実際に削除されるのは48時間以内となり、削除が実行されるまでは普通に取得できるので注意
TTLはunix秒で指定する。
項目にTTL管理用の属性をNumber型で追加し、テーブル > アクション > TTL管理 > TTL属性欄に追加した属性名を入力
する
例:
TTL属性としてttl_attr
を指定しておく。
項目にttl_attr
を追加する。
ttl_attr
の値を1598886000
にしておくと、2020/09/01 00:00:00
を過ぎた際に項目が削除される。
※ttl_attr
がない項目は期限なし
気を付けたいこと
項目の最大サイズ
1項目の最大サイズは400KB。(公式)