入門閱讀時間 2 分鐘

如何檢視、瀏覽與編輯 DynamoDB 資料

你對 DynamoDB 資料表所做的每一個「查看」或「變更」,都對應到一小組 API 操作之一 — GetItemQueryScanPutItemUpdateItemDeleteItem。 底下沒有關聯式的資料表檢視器:「瀏覽一張資料表」字面上就是一個 Scan,而「編輯一列」是針對某個主鍵的一個 UpdateItem。知道每次點擊對應到哪個 操作,是一次便宜的讀取與一次你沒打算跑的整表 掃描之間的差別。

DynoTable 是這些操作之上的一個 GUI — 它在觸及線路之前,會先給你看你 即將執行的是哪個操作,以及成本。

如何瀏覽一張 DynamoDB 資料表

開啟一張資料表來「看看裡面有什麼」是一個 Scan — 它讀取資料表或 索引中的每一個項目(AWS: 「Amazon DynamoDB 中的 Scan 操作會讀取一張資料表或一個次要 索引中的每一個項目。」)。對小型資料表可以;對大型的它就是 query vs scan 中所涵蓋的經典成本地雷。

單一 Scan 最多回傳 1 MB 的資料,然後交給你一個 LastEvaluatedKey 去 取下一個分頁 — 所以「瀏覽整張資料表」其實是一個分頁迴圈 (AWS: 「單一 Scan 請求最多可取回 1 MB 的資料」,且「Scan 回應中的 LastEvaluatedKey 應作為下一個 Scan 請求的 ExclusiveStartKey」)。請見 分頁了解游標如何運作、以及為什麼這裡不存在 位移式的頁碼。

如何過濾/掃描 DynamoDB 資料

陷阱:過濾運算式不會替你省下一次掃描。DynamoDB 在讀取完成 之後才套用過濾,所以你為每一個掃描過的項目付費 — 而不只是你 保留的資料列。

過濾運算式是在 Scan 結束後、但在回傳結果前 套用。因此,不論是否有過濾運算式,Scan 都消耗相同的讀取容量。 — AWS Scan 文件

回應讓這點可見:ScannedCount 是「在套用任何 ScanFilter 之前所評估的項目數量」,而 Count 是過濾後存活的數量 (AWS)。 高 ScannedCount 搭配很小的 Count,正是低效率掃描的特徵。

如何查詢一張 DynamoDB 資料表

一個 Query 是便宜、精準的讀取 — 但它需要一個分割鍵。依據 AWS: 「你必須提供分割鍵屬性的名稱,以及該屬性的單一 值。Query 回傳所有帶該分割鍵值的項目。你可選擇性地 提供一個排序鍵屬性,並使用比較運算子來精煉搜尋 結果。」

所以一個 Query 只讀取單一分割鍵下的項目,可選由 排序鍵條件縮小 — 從不是整張資料表。沒有分割鍵,就沒有 Query:你 回到一個 Scan。那個選擇是 DynamoDB 中最重要的單一成本決策;完整 拆解在 query vs scan 中。

要在不手寫佔位符語法的情況下組裝 KeyConditionExpression / FilterExpression,請用 DynamoDB Expression Builder — 它吐出 API 期待的確切 names/values 對應。

如何在 DynamoDB 中編輯一個項目

編輯一個項目是針對它完整主鍵的一個 UpdateItem。你不會 重寫整個項目 — 你提供一個更新運算式,只指名你 正在變更的屬性:

UpdateItem
  Key:              { "PK": "USER#42", "SK": "PROFILE" }
  UpdateExpression: SET email = :e, updatedAt = :t

兩個會絆倒人的事實,都來自 AWS 項目文件

  • 你必須指定完整的主鍵,而不只是它的一部分。 在一張 複合鍵資料表上那是分割鍵排序鍵。你無法用一個 任意屬性「編輯一列」 — 那需要先用一次掃描來找到鍵。
  • UpdateItem 是一個 upsert。 「如果指定鍵的項目不存在, UpdateItem 會建立一個新項目。否則,它會修改既有項目的 屬性。」鍵打錯字會靜默地建立一個新項目,而不是報錯。

如何刪除一個項目

一個 DeleteItem,同樣以完整主鍵作為鍵: 「DeleteItem 刪除帶指定鍵的項目」 (AWS)。 與編輯相同的規則 — 你需要完整的鍵,所以刪除「所有 status = 'open' 的列」不是一次呼叫;你要掃描/查詢找到鍵,再逐一刪除。 BatchWriteItem 把最多 25 個 put/delete 請求綁在一起 (AWS: 「BatchWriteItem 操作最多可包含 25 個個別的 PutItemDeleteItem 請求」),但每個仍針對一個鍵 — 沒有 DELETE … WHERE

如何檢視巢狀/JSON 資料

DynamoDB 項目以一個帶型別標記的線路格式(DynamoDB-JSON)儲存,其中每個 值都帶著一個一或兩個字母的型別描述子(SNMLSS… — 完整 描述子清單在 AWS 資料型別文件中)。 純 JSON 沒有 set 型別,所以一個陣列往返時會變成一個 list(L),永遠不是字串 set(SS) — 這是一個真實的轉換限制,不是顯示錯誤。完整的型別對應在 DynamoDB 資料型別中;要把一個 DynamoDB-JSON blob 轉成純 JSON 再轉回來,請用 DynamoDB JSON 轉換器

超越瀏覽與編輯:DynamoDB 做不到的查詢

Scan/Query/UpdateItem 涵蓋檢視與編輯,但它們無法分析 — DynamoDB 沒有 JOINGROUP BY,也沒有像 COUNT/SUM 的彙總函式,而 PartiQL 也沒有加上它們:它的 SELECT 文法 就是 SELECT … FROM table [WHERE …] [ORDER BY …],沒有 join 或分組子句 (AWS PartiQL SELECT 參考), 所以每個敘述都對應到單一的 Get/Query/Scan/Put/Update/Delete。DynoTable 的 SQL Workbench 填補那個缺口,方法是把你的資料表透過 DynamoDB 真正的查詢 執行階段具現化,並在上面執行 SQL — 在 DynamoDB 存取模式規則之內的 SQL — 但對日常的瀏覽與編輯,上面那些操作就是整個工具箱。

常見問題

我要如何在沒有 AWS 主控台的情況下檢視 DynamoDB 資料? 用一個發出同樣 Scan/Query 呼叫的桌面 GUI。AWS 主控台 透過分頁掃描來瀏覽資料表;像 DynoTable 這類專用用戶端做同樣的事,但 會顯示消耗的容量與你正在執行的操作。

我要如何編輯一個 DynamoDB 項目? 針對該項目完整的主鍵發出一個 UpdateItem,帶一個 SET 更新 運算式只指名你正在變更的屬性。在 GUI 中,行內編輯 那個儲存格 — 它會替你編譯成那個 UpdateItem

為什麼過濾仍然花費一次整表掃描? 因為 DynamoDB 在掃描讀取項目之後才套用過濾。被過濾掉的 項目仍被讀取並計費。要降低成本,請按分割鍵(或一個 GSI)查詢,而非掃描。

我能一次更新很多項目嗎? 不能在一次呼叫中。UpdateItem/DeleteItem 各針對單一主鍵;沒有 UPDATE … WHERE。你要掃描/查詢收集鍵,再逐一寫入(每個 BatchWriteItem 最多 25 個)。

我能用同樣的方式瀏覽一張 DynamoDB Local 資料表嗎? 能 — 把同一個 GUI 指向本機端點。請見 DynamoDB Local

想瀏覽、過濾並行內編輯 DynamoDB 資料表 — 並執行 PartiQL 做不到的 SQL 嗎?下載 DynoTable

已更新