AWS - DynamoDB GSI VS LSI


DynamoDB GSI

DynamoDB Global Secondary Index(GSI) 在 DynamoDB 上為一張 Table 建立的 『跨分區、可獨立查詢鍵』索引,允許用不同的 Partition Key/Sort Key 查詢資料,並有自己儲存與吞吐特性(通常為 eventually consistent)


基本概念

  • GSI 有自己的 Partition Key 與 Optional 的 Sort Key,可以與 DynamoDB Table 的不同
  • GSI 儲存的是表中被投影(projected) 的屬性的一份副本(或不份副本)
  • GSI 是跨分區的(global),適合跨整個表做查詢,而不只局限於原主鍵的 partition

寫入與一致性行為

  • 寫入到主表時,DynamoDB 會同時『異步』將變更資料複製到相關 GSI(因此 GSI 查詢通常是 eventually consistent)
  • 這代表:剛寫入主表後立即查 GSI 可能看不到最新資料
  • 使用 DynamoDB Transactions(TransactWrite) 可保證多項目一致性,交易也會處理 GSI 的更新(交易內的各項變更原子套用)
  • 如果項目在 GSI Index Key 屬性為 null -> 該項目 **不會寫入該 GSI(形成 sparse index,可用於解省空間或特定過濾)**。

投影(Projection Types)

  • KEYS_ONLY: 只儲存主鍵與 GSI Key(最省空間)
  • INCLUDE: 儲存文指定的附加屬性(自訂清單)
  • ALL: 儲存整個 item 的副本(最耗空間、讀取最快)

容量與成本(讀寫與儲存)

  • Provisioned mode: GSI 可有自己 provisioned RCU/WCU(過去寫入會消耗 GSI 的 WCU)
  • On-Demand: 自動按需計費
  • 寫入成本: 每次寫主表若影響 GSI,會額外產生 GSI 的寫入消耗(因此高寫量下成本會放大)
  • 儲存成本: GSI 儲存被投影的資料,會產生成本(ALL 投影最貴)

性能/熱點問題

  • GSI 會分散到多 Parition, 若 GSI Parition key 分佈不均會出現 hot parition(寫入瓶頸)
  • 高寫入熱點常用 write sharding(在 index key 加隨機 prefix) 解決,並在讀取端再合併
  • GSI 更新的延遲受 table 的寫入速率與分區分佈影響,大量突發寫入可能造成 GSI 更新 Cache 或被 throttle

使用限制與操作行為

  • 可以在表建立後新增或刪除 GSI(建立時會做 Backfill,刪除會移除索引資料)。
  • 新增 GSI 時會觸發 後台 backfill(掃描表並建立索引),這期間可能影響表的吞吐。
  • GSI 的項目數量與大小會計入儲存限制;單項目大小限制仍適用(400 KB)。
  • 每個 region / account 有 GSI 數量上限(可調用限額提升)。

設計建議(常用 patterns)

  • 為每個 access pattern 建一個 GSI(單表設計的核心)。
  • 使用 sparse GSI:只有當特定屬性存在才會被索引(用於某些狀態或類別的查詢)。
  • 選擇精簡投影(INCLUDE / KEYS_ONLY)以節省儲存和寫入成本。
  • 避免使用高基數單一 key 導致 hotspot:使用複合 key 或 sharding。
  • 在高寫入場景,考慮 on-demand 或適當 provisioned + auto-scaling。

監控與排錯重點(CloudWatch 指標)

  • 監控:ConsumedWriteCapacityUnits、ConsumedReadCapacityUnits(GSI 層面)
  • 錯誤/瓶頸:ThrottledRequests、ProvisionedWriteCapacityExceeded(若 provisioned)
  • 延遲觀察:查詢結果不一致 → 檢查表到 GSI 的同步延遲與 backfill 狀態。
  • 若查不到資料:檢查該 item 是否有 GSI key 屬性(若沒有,項目不會出現在 GSI)。

成本/效能實務小技巧

  • 減少 GSI 的投影屬性以降低儲存與寫操作。
  • 把 write-heavy attributes 放在主表且只在必要時投影到 GSI。
  • 使用 adaptive capacity / auto scaling 並設 alert 以避免 throttle。
  • 大量新增 GSI 時,分批啟用或在低流量時新增以減少 backfill 影響。

備註

  • GSI 可後加(vs LSI 必須建表時定義) → 考試常考差別題。
  • GSI 有自己的吞吐與儲存成本 → 寫入會消耗主表 + GSI 的寫入單位。
  • 若索引鍵屬性不存在,該 item 不會出現在 GSI(sparse index)。

GSI VS LSI 表格整理

比較項目GSI (Global Secondary Index)LSI (Local Secondary Index)
Partition Key可以不同於主表必須相同於主表
Sort Key可不同必須不同於主表 SK
建立時間✅ 隨時可新增/刪除(建後會 backfill)❌ 必須在建表時定義
容量模型獨立 RCU/WCU(Provisioned)共用主表吞吐量
儲存空間✅ 有自己儲存(多一份 copy)❌ 共用主表 storage
一致性Eventually consistent(預設)✅ 可支援 Strong Consistent Read
Query 範圍跨整表(Global)限同一 partition(Local)
Sparse Index 支援✅ ✔✅ ✔
成本影響雙倍寫入成本(含儲存費)✅ 寫入只算主表成本
Hot partition 風險高(若 PK 分佈不均)與主表 PK 相同(風險相同)
最大數量20 / table(上限可調)最大 5 / table(固定)
典型用途非主鍵屬性查詢 / 多 access patterns單 PK 多排序條件查詢