皆さんはDynamoDBから値を取得するとき、スキャンとクエリのどちらを使っていますか?
2つともテーブルからデータを取得できることは同じですが、その仕組みは全くの別物となります。
今回はこの2つの検索方法について解説します。
目次
1. 検索の種類
このようなテーブルが存在します。
社員ID (🔑PK) | 資格ID (🔑SK) | 取得日 (🗝️LSI-SK) |
1 | 1 | 2025-01-01 |
1 | 3 | 2025-01-31 |
1 | 5 | 2025-02-01 |
1 | 8 | 2025-03-20 |
1 | 9 | 2025-04-01 |
2 | 1 | 2025-01-01 |
2 | 5 | 2025-01-31 |
・・・ | ・・・ | ・・・ |
999 | 100 | 2025-02-10 |
次の条件でデータを取得したい。
社員IDが "1" で、2025年1~3月の期間内に取得した資格IDを抽出したい
Scan
スキャンは、テーブル全体をフルスキャンして全データを取得する操作です。
テーブル全体を読み取るため、パフォーマンスやコストの観点からはあまり効率的な操作ではありません。
★特徴
- PK/SKでの条件指定が出来ない
- テーブル内のすべてのアイテムを読み取るため、非常にコストがかかる
- 取得条件を指定した場合は、フルスキャン後にフィルタリングが行われる
特に最後のポイントが重要で、例えばRDBMSにおけるSQLの場合は、先にWHERE句で指定した条件が効いてレコード数が絞られた上で、結果を取得できます。
しかし、DynamoDBのスキャンは必ずフルスキャンが行われ、全てのデータが取得されます。
全データを取得後に指定条件でフィルタリングされ、結果としてレスポンスされます。
つまり、取得コスト(キャパシティユニット)も取得時間も膨大となってしまいます。
★データ取得の流れ
① 社員資格テーブルから全データを取得する
社員ID (🔑PK) | 資格ID (🔑SK) | 取得日 (🗝️LSI-SK) |
1 | 1 | 2025-01-01 |
1 | 3 | 2025-01-31 |
1 | 5 | 2025-02-01 |
1 | 8 | 2025-03-20 |
1 | 13 | 2025-04-01 |
2 | 1 | 2025-01-01 |
2 | 5 | 2025-01-31 |
・・・ | ・・・ | ・・・ |
999 | 100 | 2025-02-10 |
② 社員IDが「1」、取得日が「2025年1~3月」でフィルタリングを行う
社員ID (🔑PK) | 資格ID (🔑SK) | 取得日 (🗝️LSI-SK) |
1 | 1 | 2025-01-01 |
1 | 3 | 2025-01-31 |
1 | 5 | 2025-02-01 |
1 | 8 | 2025-03-20 |
~ データ取得完了 ~
スキャンで条件を指定する場合は、この2ステップが行われます。
Query
クエリは、PK/SKに限り先に条件を指定することができます。
「先に」というのはRDBMSのWHERE句と同じように、データの取得前に条件指定が適用されます。
★特徴
- PK/SKでの条件指定が可能
- PK/SK以外での条件指定も可能だが、この場合はデータ取得後のフィルタリングとなる
スキャンとの大きな違いは、やはりPK/SKでの条件指定が可能となる点でしょう。
しかし、条件指定には大きな制約があることもポイントです。
★ルール
- PKへの条件指定は完全一致のみが可能
- SKは範囲や前方一致などある程度の条件指定にも対応しているが、SKのみでの指定は不可
- SKに条件を指定する場合は、必ずPKにも条件を指定しなければならない
- PKとSK以外の項目には条件を指定できない
最後のポイントに「PKとSK以外の項目には条件を指定できない」とありますが、これはあくまでもデータ取得前に条件指定を適用することができないというだけで、データ取得後におけるフィルタリングは可能です。
(クエリの厳しい制約を突破可能とするテーブル設計例はコチラ)
★データ取得の流れ
① 社員ID (PK) が「1」、取得日 (LSI-SK) が「2025年1~3月」の範囲を条件指定する
社員ID (🔑PK) | 資格ID (🔑SK) | 取得日 (🗝️LSI-SK) |
1 | 1 | 2025-01-01 |
1 | 3 | 2025-01-31 |
1 | 5 | 2025-02-01 |
1 | 8 | 2025-03-20 |
~ データ取得完了 ~
クエリの場合はこの1ステップのみで完結します。
比較
Scan | Query | |
データ取得範囲 | テーブル全体 | PK/SKを基に絞り込み |
パフォーマンス | 必ず全件検索が行われ、非効率 | インデックス使用で効率的 |
使用可能なキー | なし | PK/SK |
フィルタリング | 結果取得後にフィルタリング可能 | 結果取得後にフィルタリング可能 |
2. まとめ
スキャンはテーブル全体を検索するため、パフォーマンスが悪く、コストも高くなります。
使用シーンとしても明確で、テーブル全体のデータを取得したい場合や、クエリでの条件指定が難しい場合にのみ使用することが望ましいです。
クエリはPK/SKを指定してデータを絞り込むため、高速で効率的にデータを取得できます。
特定の条件に基づいてデータを取得したい場合は、クエリの方が適しています。
3. Scanは最後の切り札
スキャンはマダンテ💥であって、エリクサー💊でもあります。
最後の切り札って、追い詰められたときに出しますよね。
DynamoDBだってそうです。
まずはクエリで試してみて、どうしてもダメな場合にのみ力を解放しましょう⚡