用 AWS CLI 查詢 DynamoDB 的 GSI
查詢全域次要索引就是一次普通的 aws dynamodb query 加上一個旗標:--index-name。索引鍵條件接著鎖定的是索引的索引鍵,而不是資料表的 — 這裡的 AlbumTitle-index 讓我們能依專輯取歌,而基礎資料表(Artist 加 SongTitle)不掃描是辦不到這個存取模式的。
程式碼
aws dynamodb query \
--table-name 'Music' \
--index-name 'AlbumTitle-index' \
--key-condition-expression '#hashKey = :hashKeyValue' \
--expression-attribute-names '{"#hashKey":"AlbumTitle"}' \
--expression-attribute-values '{":hashKeyValue":{"S":"Danzon"}}'輸出是以 DynamoDB JSON 呈現的相符項目:
{
"Items": [
{"Artist": {"S": "Arturo Sandoval"}, "SongTitle": {"S": "Cubano Chant"}, ...}
],
"Count": 2,
"ScannedCount": 2
}說明
這次查詢對基礎資料表完全不計費。加上 --return-consumed-capacity INDEXES,分帳就一清二楚:
"ConsumedCapacity": {
"CapacityUnits": 132.0,
"Table": {"CapacityUnits": 0.0},
"GlobalSecondaryIndexes": {"AlbumTitle-index": {"CapacityUnits": 132.0}}
}資料表是零,全部算在索引上。GSI 是一張獨立的資料表,有自己的索引鍵結構、自己的分割區與自己的容量,讀它從不碰到基礎資料表。這也是為什麼 GSI 有它自己的節流故事:被節流的 GSI 會連帶節流基礎資料表的寫入,即使讀取從來不會跨過去。
--consistent-read 會被回絕,不是被降級。GSI 是非同步複寫的,沒有任何旗標能改變這件事:
aws: [ERROR]: An error occurred (ValidationException) when calling the Query operation: Consistent reads are not supported on global secondary indexes結束碼 254。API 參考文件事先就說了同樣的話:"Strongly consistent reads are not supported on global secondary indexes. If you query a global secondary index with ConsistentRead set to true, you will receive a ValidationException"(2026-07-28 取得)。本地次要索引倒是接受它,而這正是少數幾個真正該選 LSI 的理由之一。延遲本身則在為什麼 GSI 是最終一致的裡談。
沒有索引鍵的項目,就只是不在索引裡。在同一張資料表上數過:基礎資料表 35 個項目,AlbumTitle-index 裡 32 個。少掉的那三個根本沒有 AlbumTitle 屬性,以 attribute_not_exists(AlbumTitle) 的掃描確認過。沒有任何東西報錯,也沒有任何東西警告。這就是稀疏索引模式:當你只為想被索引的那些列寫入旗標屬性時,它是刻意的設計;當你以為索引會鏡射整張資料表時,它是一個無聲的資料遺失臭蟲。
你只拿得到索引投影出來的東西。"If you query or scan a global secondary index, you can only request attributes that are projected into the index. Global secondary index queries cannot fetch attributes from the parent table"(2026-07-28 取得)。在 KEYS_ONLY 或 INCLUDE 索引上,這代表每一筆結果都要再一次 get-item 去補齊其餘部分,而那正是你本來想避開的 N+1。投影在索引建立時就定下來,之後無法更改;在你挑定之前請先看索引投影。
索引鍵不是唯一的。很多項目可以共用同一個 AlbumTitle,所以 GSI 查詢回傳的是一個集合,而同等的資料表查詢會回傳單一項目。也正是因為這個原因,對 GSI 做 get-item 這種事根本不存在。
分頁的行為跟任何資料表查詢一樣,包括 CLI 那個對自動分頁結果只回報單一頁 ConsumedCapacity 的習慣。那件事在用 AWS CLI 執行 Query 裡有詳細測量;這裡的旗標是一樣的。
改用視覺化操作
索引查詢比資料表查詢多了幾個活動零件:挑對索引、索引自己的索引鍵名稱,還有一個可能沒帶著你需要的屬性的投影。免費的 DynamoDB Query Builder 讓你選索引、依它的索引鍵組出索引鍵條件,並產出 CLI 指令。
想看看一張資料表實際上有哪些索引、並對你自己的資料查詢它們 — 列出投影、隨捲動分頁的網格、把請求複製回去變成 CLI 指令 — 請下載 DynoTable。
相關範例
- 在 Node.js 中查詢 DynamoDB 的 GSI — 用 AWS SDK v3 做同一種索引查詢。
- 在 Python 中查詢 DynamoDB 的 GSI — 用 boto3 做同一種索引查詢。
- GSI 與 LSI 的比較 — 哪一種索引型別合乎你的存取模式。
- 「The table does not have the specified index」 — 索引名稱不符(GSI 名稱區分大小寫)。
- 「Consistent reads are not supported on global secondary indexes」 — 為什麼一致性讀取旗標在 GSI 上會失敗。
參考資料
- Query — Amazon DynamoDB API Reference
- query — AWS CLI Command Reference
- Using Global Secondary Indexes in DynamoDB — Amazon DynamoDB Developer Guide
- Using AWS CLI pagination options — AWS CLI User Guide
已於 2026-07-28 以 aws-cli/2.36.9,在一張帶有投影為 ALL 的 AlbumTitle-index 的 Music 資料表上,對照連接埠 9000 上的 DynamoDB Local(amazon/dynamodb-local)重現。上方的錯誤文字、容量分帳與項目數量都是擷取到的輸出。