DynamoDB を降順にクエリする方法
デフォルトでは DynamoDB の Query はアイテムを昇順のソートキー順で返します。しかし
たいていの「最新をくれ」というアクセスパターンは、その逆——新しい順を望みます。つまみは
Query 上の単一のブール値、ScanIndexForward です。これを false に設定すると、同じ
クエリがパーティションを逆向きに読みます。
パラメータは1つですが、人をつまずかせます。事後に_結果_をソートすること (DynamoDB は それをしません) と混同しやすく、名前が制御する内容とは逆向きに読めるからです。
DynamoDB を降順にクエリするにはどうしますか?
Query に ScanIndexForward=false を設定します。デフォルトでは DynamoDB は
アイテムを昇順のソートキー順で返します。この単一のブール値を反転させるとパーティションを
逆向きに読み、ソートキーがタイムスタンプやシーケンスのときに新しい順の結果が得られます。
変わるのは順序だけで、どのアイテムが一致するかは変わらず、逆向きの読み取りは順方向と
まったく同じコストです。
ScanIndexForward=true(デフォルト) → 昇順のソートキー順。ScanIndexForward=false→ 降順——ソートキーがタイムスタンプやシーケンスのときは 新しい順。- 影響するのは順序だけで、どのアイテムが一致するかではありません——それはやはりキー 条件が決めます。
- 無料です。 逆順は順方向と同じコストです。DynamoDB はどちらにせよパーティションの 格納順を読みます。
Limitと併用して、「最新の N 件」を1回の安い読み取りで得ましょう。
問題:「最新を先に見せて」
マルチプレイヤーのリーダーボードを運営していて、各プレイヤーのスコアイベントを1つの パーティションキーの下に、増加するタイムスタンプでソートして格納しているとします。
PK: GAME#42 SK: SCORE#2026-06-27T10:00:00Z points
PK: GAME#42 SK: SCORE#2026-06-27T10:05:00Z points
PK: GAME#42 SK: SCORE#2026-06-27T10:09:00Z pointsダッシュボードは最新のスコアを必要とします。GAME#42 への素の Query はそれらを
古い順に返すので、すべてを読んでアプリで反転したくなります——無駄で、Limit を追加した
瞬間に壊れます。DynamoDB は直接それらを新しい順で返せます。
ScanIndexForward の仕組み
パーティション内のアイテムは、物理的にソートキーで順序付けて格納されます。Query は
その順序を歩き、ScanIndexForward は歩く方向を選ぶだけです。
true(デフォルト) — 最も低いソートキーから始めて、上へ歩く (昇順)。false— 最も高いソートキーから始めて、下へ歩く (降順)。
肝心なのは、これは読み取りの性質であって、テーブルの性質ではないことです——同じ
アイテム、同じキー条件で、逆にするだけです。そして DynamoDB はすでにソートされたデータに
対して方向を選んでいるだけなので、降順の読み取りは昇順と
まったく同じくらい安い
です。Limit=10 と組み合わせれば、「最新の 10 件のスコアイベント」を単一の最小コストの
Query で得られます。
1つの微妙な点:降順の結果セットを後方にページングするとき、
LastEvaluatedKey/ExclusiveStartKey のカーソルはやはり機能します——ただし同じクエリの
すべてのページを通じて ScanIndexForward=false を一貫させてください。さもないとカーソルの
方向と順序が食い違います。
DynoTable でクエリを組み立てる
キー条件そのものを組み立てる (そして対応する属性名/値のマップを見る) には、
DynamoDB 式ビルダーを使いましょう。リクエスト全体 —
インデックス、Limit、ScanIndexForward を含めて — は、
クエリビルダーが Query を組み立て、実行可能な
SDK v3、CLI、boto3 のプログラムを出力します。
DynoTable では、選んだキーでタブを読み、タブのソート方向をトグルで設定します——
ScanIndexForward を手書きする必要はありません。反転させて新しい順の結果をプレビュー
しましょう。

落とし穴と次のステップ
ScanIndexForwardは反転するのであって、任意の属性でソートするのではない。 順序は 常にソートキーによります——他の何かでソートするには、その属性を (しばしば GSI経由で) ソートキー_として_持つ必要があります。- アプリで全部読んで反転しない。 フラグを設定して
Limitを追加しましょう。 - ページング中はフラグを一貫させる。 複数ページのクエリで、さもないとカーソルが順序と 争います。
- 数値で新しい順にしたい? Number 型のソートキーはすでに数値でソートされます。数値を 文字列のソートキーに埋め込んだ場合にのみ、辞書順が一致するよう ゼロ埋めする必要があります。
- 関連:ソートキー戦略と ページネーション。
API パラメータに触れずに結果の順序を反転したいですか? DynoTable をダウンロードして、自分のテーブルを直接クエリしましょう。
複合ソートキーと数値ソートキー
降順は「最新」というこちらの頭の中のモデルではなく、ソートキーの型のルールに従います。
| ソートキーの保存形式 | 降順で得られるもの | 落とし穴 |
|---|---|---|
ISO-8601 の UTC 文字列 2026-06-27T10:09:00Z | 最も新しいタイムスタンプが先頭 | タイムゾーンを固定すれば、辞書順が時系列と一致する |
ゼロ埋めしたエポック文字列 00000000001009 | 最も大きいシーケンスが先頭 | ゼロ埋めしない数値は誤って並ぶ("9" > "10")— ゼロ埋めを参照 |
Number 型 N | 最も大きい数値が先頭 | 文字列ではなく、自然な数値順 |
ステータス接頭辞 STATUS#open#... | SK 全体に対する逆辞書順 | 接尾辞に符号化していない限り、「最近開いた順」とは別物 |
「最新」がソートキー以外の何か(たとえば同じゲームのパーティション内で points 順)を意味する
なら、その指標はソートキーの中(あるいはソートキーが points の GSI)に必要であって、
アプリケーションコードでのクエリ後のソートでは足りません。
降順の読み取りにおける Limit
Limit が上限を設けるのは評価されたアイテム数であって、フィルター後に返るアイテム数では
ありません。時系列のソートキーに対して ScanIndexForward=false と Limit=10 を組み合わせれば、
1 回のパーティション読み取りで直近 10 件のイベントを取得できます。
コストの例: 1 回の降順 Query で 2 KB のアイテム 10 件は 20 KB に触れ、結果整合性で 3 RCU に
なります(4 KB ブロック単位に切り上げ)。アプリケーションコードで反転するために 10,000 件の
イベントを持つパーティション全体を読むと、およそ 20 MB に触れ、同じ UI ウィジェットのために
数千 RCU がかかります。Limit を決める前に、アイテムサイズ計算ツールで
パーティションの大きさをモデリングしましょう。
ページングも方向を保つ
ExclusiveStartKey でページングするときは、すべてのリクエストで ScanIndexForward を同じに
保ってください。ページの途中でフラグを反転すると、カーソルの意味が逆になります — 行を飛ばしたり
重複させたりする可能性があります。
「もっと読み込む」を公開する API では、LastEvaluatedKey を不透明な base64 として符号化しましょう。
クライアントがソートキーの構成要素を書き換えるべきではありません。トークンのパターンについては
ページネーションを参照してください。
PartiQL と SDK の対応
PartiQL の ExecuteStatement クエリは、実行系がキー条件による読み取りに対応づけられる場合、
下層の Query パラメータを通じて同じ順序のセマンティクスを受け取ります。
クエリビルダーは ScanIndexForward を明示的に組み込んだ
SDK v3、CLI、boto3 のプログラムを出力します — チームが PartiQL のアドホックなクエリと本番の
SDK コードを併用している場合に役立ちます。
降順を使うアクセスパターン
- アクティビティフィード —
SKは ISO のタイムスタンプ。降順とLimitで直近のウィンドウが 得られます。 - リーダーボード — 数値のソートキー
score。パーティションキーが 1 つのゲームやシーズンに 絞られていれば、降順で上位スコアが浮かび上がります。 - 監査ログ — 追記のみの
EVENT#<ts>ソートキー。GSI なしで、降順が最新のイベントを先頭に 表示します。
UI が昇順の履歴(「古い順に表示」)も必要とする場合、同じクエリを ScanIndexForward=true で
実行すれば、データを二重に持ったりインデックスを 2 本維持したりせずに済みます。
実データでトグルを試す
DynoTable を接続し、時系列のソートキーを持つパーティションでクエリタブを開き、昇順と降順を
切り替えて、API パラメータを編集せずにグリッドが並び替わるのを見てください。オペレーション
ログで消費キャパシティを比べましょう — 同じ Limit での順方向と逆方向の読み取りは一致するはずです。


