使用 AWS CLI 的 DynamoDB Query
aws dynamodb query 會讀取一個分割區,並可選擇用排序索引鍵再收窄(Query 與 Scan 的比較說明何時該這麼做,鍵條件運算式則列出每一個合法的運算子)。CLI 額外疊上去的,是它自己的一層分頁邏輯,而這也是這個指令上大多數意外的來源。
程式碼
aws dynamodb query \
--table-name 'Music' \
--key-condition-expression '#hashKey = :hashKeyValue AND begins_with(#rangeKey, :rangeKeyValue)' \
--expression-attribute-names '{"#hashKey":"Artist","#rangeKey":"SongTitle"}' \
--expression-attribute-values '{":hashKeyValue":{"S":"Arturo Sandoval"},":rangeKeyValue":{"S":"C"}}'#hashKey/#rangeKey 這兩個別名透過 --expression-attribute-names 解析成 Artist/SongTitle,這正是讓保留字不至於弄壞指令的關鍵。想要排序索引鍵由大到小排列,請加上 --no-scan-index-forward;預設是由小到大。
分頁
CLI 預設會自動分頁 — 它會在內部跟著 LastEvaluatedKey 走,並把合併後的結果印出來。若要手動分頁(例如結果集很大時),請用這些旗標控制:
aws dynamodb query \
--table-name 'Music' \
--key-condition-expression '#hashKey = :hashKeyValue' \
--expression-attribute-names '{"#hashKey":"Artist"}' \
--expression-attribute-values '{":hashKeyValue":{"S":"Arturo Sandoval"}}' \
--page-size 100 \
--max-items 50
# The output includes a "NextToken"; pass it back with --starting-token to continue.說明
CLI 把分頁藏了起來,連成本數字也一起藏。先在一個分割區裡塞進 30 筆各約 60 KB 的項目,總共約 1.8 MB,因此會是兩個服務頁;接著用 --return-consumed-capacity TOTAL 以三種方式跑同一個查詢:
default (auto-paginate) Count: 30 CapacityUnits: 132.0 LastEvaluatedKey: null
--no-paginate Count: 18 CapacityUnits: 132.0 LastEvaluatedKey: {…S017}
--max-items 3 Count: 18 items printed: 3 NextToken: eyJFeGNsdXNpdmVTdGFydEtleSI6…手動分頁才看得到真正的成本:第 1 頁是 18 筆、132.0 單位,第 2 頁是 12 筆、88.0 單位,所以這個查詢實際消耗了 220.0 個讀取單位。自動分頁的那一次執行發出了兩次呼叫、回傳全部 30 筆項目,卻只回報 132.0。CLI 會跨頁合併 Items 與 Count,但不會合併 ConsumedCapacity,所以印出來的數字把這個查詢低估了 40%。如果你是靠 CLI 輸出來估算容量,請改用手動分頁,否則你只會照著一頁的量來估。
--max-items 是列印上限,不是 Limit。上面第三次執行印出三筆項目,卻仍然回報 Count: 18 與 ScannedCount: 18,因為它截斷的那個服務頁就是 18 筆、大約 1 MB。你為整頁都付了錢。真正會限制讀取量的 DynamoDB 參數是 Limit,而 CLI 把它暴露成 --page-size。
所以這兩個旗標做的是毫不相干的事。--page-size 會變成 API 的 Limit,決定每次服務呼叫讀多少;--max-items 只決定合併後的結果有多少會送到你的終端機,並為剩下的部分發出一個 NextToken。那個 token 是 CLI 自己記帳用的一段 base64 資料,不是 DynamoDB 的 LastEvaluatedKey,而它是透過 --starting-token 傳回去的。
沒有 --limit,也沒有 --exclusive-start-key。在 2.36.9 上執行 aws dynamodb query help,語法摘要裡兩個都找不到:CLI 拿掉了 DynamoDB 那兩個分頁參數,換成它自己的三個。所以那個最自然的迴圈 — 從一次呼叫取出 LastEvaluatedKey 再餵給下一次 — 根本沒有旗標可以餵。回到原始 API 的路徑是 --cli-input-json,它會逐字接下整個請求:
--cli-input-json with "Limit": 5 and an "ExclusiveStartKey"
→ Count: 5 CapacityUnits: 37.0 LastEvaluatedKey: {"Artist":…,"SongTitle":"S007"}請注意這同時也把分頁器關掉了:即使沒有加 --no-paginate,那次執行也只回傳一頁與一個真正的 LastEvaluatedKey。如果你要為一個很大的分割區寫一段 shell 迴圈,--cli-input-json 是誠實的做法,而 --no-paginate 是快的做法。
--query 是在錢花完之後才跑的。全域的 --query 旗標是套用在回應上的 JMESPath,執行在你的 shell 裡。像 Items[?Year > '2010'] 這樣的 JMESPath 運算式看起來像過濾條件,其實不是:在 JMESPath 看到之前,每一筆項目都已經被讀取、傳輸並計費。--filter-expression 至少能省下資料傳輸,但 AWS 明確寫著它「is applied after the items have already been read; the process of filtering does not consume any additional read capacity units」(擷取於 2026-07-28)。這句話是雙面刃,因為它同時也表示過濾條件不會讓讀取量變少。唯一能少讀的方法,是更收窄的鍵條件或一個索引。
不管你要求什麼,一頁就是 1 MB。「A single Query operation will read up to the maximum number of items set (if using the Limit parameter) or a maximum of 1 MB of data」(擷取於 2026-07-28)。比這更寬的分割區一定會分頁,這也是為什麼上面那個 30 筆的查詢從來不是一次呼叫。
查詢索引要多一個旗標。--index-name 會把鍵條件切換到該索引的鍵上;而全域次要索引也會拒絕 --consistent-read。請見使用 AWS CLI 查詢 GSI。
改用視覺化操作
要在一個指令裡同時把鍵條件、那兩張佔位符對應表與分頁迴圈都弄對,正是這裡真正的難處。免費的 DynamoDB Query Builder 會替你組出請求(含索引與分頁),並輸出成一段可直接執行的 CLI 指令。
想對你自己的資料表執行查詢 — 鍵條件表單、隨著捲動自動分頁的表格、把請求複製回一段 CLI 指令 — 請下載 DynoTable。
相關指南
- Query 與 Scan 的比較 — 為什麼
query才是正確的預設值。 - 分頁 —
LastEvaluatedKey、ExclusiveStartKey,以及為什麼Limit不是頁面大小。 - 「Query condition missed key schema element」 — 鍵條件指到了錯的屬性,或漏掉了分割區索引鍵。
- 「Query key condition not supported」 — 鍵條件不能用的運算子,例如 contains 或第二個排序索引鍵條件。
參考資料
- Query — Amazon DynamoDB API Reference
- query — AWS CLI Command Reference
- Using the pagination options in the AWS CLI — AWS CLI User Guide
- Filtering AWS CLI output — AWS CLI User Guide
- Querying tables — Amazon DynamoDB Developer Guide
已於 2026-07-28 以 aws-cli/2.36.9,對照連接埠 9000 上的 DynamoDB Local(amazon/dynamodb-local),在一個含 30 筆各約 60 KB 項目的分割區上實測。上方的筆數、token 與容量數據皆為擷取的實際輸出。DynamoDB Local 以文件所述的進位規則計算容量;請把絕對數字當成形狀的示範,在估算容量之前請對照線上服務量測你自己的資料表。