クエリとソート

SQL の WHERE のように感じるから Scan にフィルターを足し、コンソールが一致する 20 行を見せているあいだにテーブル内の全アイテムを読んで支払う。そのパターンは、本番の請求でよくある DynamoDB のコスト上の驚きだ。

DynamoDB の読み取りはキー付きだ。Query は 1 つのアイテムコレクションをソートキー順に歩き、Scan はテーブル全体に触れる。

フィルター式はキャパシティが課金されたあとで行を捨てる。ページネーションは LastEvaluatedKey を運ばなければならない。ソートは選んだインデックスのソートキー経由で行われ、アプリメモリ内の任意の列ではない。

このセクションで身につくこと

  • 機能ごとに Query と Scan を選び、パーティション範囲でその選択を防衛できる。
  • アイテムを落としたり重複させたりせず、大きな結果セットをページできる。
  • 可能ならキー条件でフィルターをかけ、読み取り後フィルターがまだいくら掛かるか知っている。
  • ソート順をソートキーにエンコードし(数値順のためのゼロパディング、可変の値は GSI キーに)、どちらの方向にも読み取れる。

読む順番

  1. Query 対 Scan: 他の読み取りガイドが理解を前提にする課金の判断。
  2. ページネーション: LastEvaluatedKey、ページループ、そして Limit が「返された行数」ではない理由。
  3. フィルタリング戦略: キー条件対フィルター式。まずキーで絞り込み、キーで絞れない分だけをフィルターにかける。
  4. なぜ Scan は遅くて高いのか: テーブル成長対パーティション成長。ワンオフの Scan が許容されるとき。
  5. 並列スキャン: バックフィルと移行のためのセグメント化 Scan。スループットのトレードオフ。
  6. ソートキー戦略: 順序がアプリ内ではなくディスク上にあるようソートキーを設計する。
  7. クエリの降順: ScanIndexForward と最新優先の読み取り。
  8. 可変ソートキー: キー属性を更新できない理由と、delete+put を避ける GSI ソートキーのパターン。
  9. ゼロパディングソート: 固定幅の数値ソートキーで TICKET#00042 が TICKET#00100 の前に並ぶようにする(パディングなしでは TICKET#100 が TICKET#42 の前に並ぶ)。
10 件中 0 件読了クイズ
DynamoDB の Query と Scan:どちらをいつ使うか
DynamoDB の Query と Scan。Query は 1 つのアイテムコレクションを読み、キー条件が選んだ分だけ課金されます。Scan はフィルターが動く前にテーブル全体を課金します。
初級読了 9 分
DynamoDB のページネーション:LastEvaluatedKey 解説
DynamoDB のページネーションの仕組み。LastEvaluatedKey と ExclusiveStartKey でループする方法、Limit がページサイズでない理由、安全なステートレスカーソルの公開方法。
初級読了 9 分
DynamoDB のフィルタリング戦略
DynamoDB のフィルタリング戦略を比較(パーティションキー、ソートキー、スパースインデックス、FilterExpression)し、どれが本当に読み取り課金を削るのかを解説。
中級読了 9 分
DynamoDB の Scan が遅くて高コストな理由
DynamoDB の Scan が遅くて高コストな理由、実際に何に対して課金されるのか、そして反射的な Scan をコストがわずかで済むキー付き Query に変える方法。
初級読了 6 分
DynamoDB のパラレルスキャン
DynamoDB のパラレルスキャンが Segment と TotalSegments でテーブル全体の読み取りをワーカーに分割する仕組み、役立つ場面、そして S3 へのエクスポートのほうが適した仕事。
上級読了 8 分
DynamoDB ソートキー戦略:3 つのパターンと使い分け
範囲読み取りのための DynamoDB ソートキー戦略。バイト順が読み取り順と一致するソートキーを設計し、1 つの Query で多くのアクセスパターンに応える。
中級読了 6 分
DynamoDB を降順にクエリする方法
ScanIndexForward=false または PartiQL の ORDER BY DESC で DynamoDB を降順にクエリする。新しい順の結果、順序がソートキーに従う理由、そしてコスト。
初級読了 6 分
変化する (可変な) 属性で DynamoDB をソートする
変化する属性で DynamoDB をソートする。キー属性が変更できない理由、削除して put するパターン、キーの付け替え、そして値を GSI のソートキーへ移す方法。
中級読了 8 分
DynamoDB におけるソートキーのゼロ埋め
DynamoDB の文字列ソートキーで "10" が "2" より前に並ぶ理由と、固定幅のゼロ埋めが辞書順のバイト順を数値順に一致させる仕組み。
中級読了 5 分
理解度チェッククイズに挑戦
このセクションで学んだ内容を確認しましょう。

PK = TEAM#billing と SK begins_with TICKET# の Query はそのチームのチケットだけを読む。千万アイテムのテーブル上で filter status = OPEN の Scan は、それでも千万アイテムすべての読み取りを課金する。

us-east-1 のオンデマンド定価では、4 KB の読み取りリクエストユニット 1 つは $0.000000125 だ。呼び出しあたりは些細だが、テーブル規模では大きい。料金計算機 が実際の読み取りレートとアイテムサイズで料金を見積もる。

並列スキャンは、バックフィルや移行のようにすべてのライブアイテムに触れなければならないジョブのために、Scan をワーカーへ分割する。増えるのは読み取りのレート であって総量ではない。請求額は逐次スキャンと同じで、早く届くだけだ。

幅の広い並列スキャンはライブトラフィックを枯渇させうる。S3 への定期的なダンプには、代わりに S3 へのエクスポートを使おう。テーブルではなく、ポイントインタイムリカバリのバックアップを読み取る。

ベーステーブルのソートキーを変えるには、テーブルでも、そのアイテムが現れるすべての GSI でも、delete と put が必要になる。可変ソートキーのガイドは、代わりに変わりやすい値を GSI のソートキーに置き、普通の UpdateItem でそれを動かす。

ゼロパディングは、ソートキーが数値 ID を運ぶ文字列のときの辞書順を直す。

DynoTable で

無料の クエリビルダー は、完全な Query または Scan リクエストを、ページネーションループ付きの実行可能なプログラム(12 の言語と SDK)か、PartiQL ステートメントとして組み立てる。

アプリでは、ビジュアルなクエリビルダーでインデックスを選べ、その実行ボタンはキー条件に応じて Query か Scan と表示されるので、どちらの読み取りに支払おうとしているのかが分かる。

DynoTable をダウンロードして、ライブテーブルに対してこれらの読み取りを実行しよう。クエリコストのステータスバーは、Workbench と PartiQL タブで実行前のヒント(プランが分かるときは ~N items · ~R RCU)を出すので、思わぬ請求が実行前に表面化する。