如何檢視、瀏覽和編輯 DynamoDB 資料
你對一張 DynamoDB 表做的每一次"檢視"或"更改",都會對映到一小組 API 操作之一——GetItem、Query、Scan、PutItem、UpdateItem、DeleteItem。底層並沒有一個關係型的表檢視器:"瀏覽一張表"字面上就是一次 Scan,而"編輯一行"是一次針對 的 UpdateItem。知道每次點選對映到哪個操作,就是一次廉價讀取與一次你本不打算執行的全表掃描之間的分水嶺。
DynoTable 是一個恰好覆蓋這些操作的圖形介面——它會在觸網之前告訴你你即將執行哪一個,以及開銷是多少。
如何瀏覽一張 DynamoDB 表
開啟一張表去"看看裡面有什麼"是一次 Scan——它讀取表或索引中的每一個項(AWS:"Amazon DynamoDB 中的 Scan 操作會讀取表或次要索引中的每一個項。")。對小表沒問題;對大表它就是 Query 與 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 與 Scan。
在 us-east-1 的按需模式下,開啟一張表去「瀏覽」它跑的是一次分頁 Scan,
按最終一致對每一個被檢查的項每 4 KB 計 0.5 個 RCU——在一張 10 GB、
行大小 1 KB 的表上用 GUI 一路滾下去,如果你把所有東西都載入進來,量級是
250 萬個 RCU。而一次針對單個分割區索引鍵的 Query 只讀那一個項集合。
瀏覽和查詢的對比可以在定價計算器裡估算。
要拼裝 KeyConditionExpression / FilterExpression 而不必手寫預留位置語法,用 DynamoDB Expression Builder——它會輸出 API 所期望的確切名稱/值對映。
如何編輯 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:"@@P11@@ 操作最多可包含 25 個獨立的 PutItem 和 DeleteItem 請求"),但每一個仍然只針對一個鍵——沒有 DELETE … WHERE。
如何檢視巢狀 / JSON 資料
DynamoDB 項以一種帶型別標籤的傳輸格式(DynamoDB-JSON)儲存,其中每個值都帶一個一或兩字母的型別描述符(S、N、M、L、SS… ——完整的描述符清單在
AWS 資料型別文件)。純 JSON 沒有 set 型別,所以一個陣列會往返成一個列表(L),絕不會是一個字串 set(SS)——這是一個真實的轉換限制,而不是顯示上的 bug。完整的型別對映在 DynamoDB 資料型別;要把一段 DynamoDB-JSON 資料轉換成純 JSON 再轉回來,用 DynamoDB JSON 轉換器。
超越瀏覽與編輯:DynamoDB 做不到的查詢
Scan/Query/UpdateItem 覆蓋了檢視和編輯,但它們無法_分析_——DynamoDB 沒有 JOIN、GROUP BY,也沒有像 COUNT/SUM 這樣的聚合函式,PartiQL 也不新增它們:它的 SELECT 語法就只是 SELECT … FROM table [WHERE …] [ORDER BY …],沒有連線或分組子句(AWS PartiQL SELECT 參考),所以每條語句都對映到單個 Get/Query/Scan/Put/Update/Delete。DynoTable 的 SQL Workbench 透過 DynamoDB 真實的查詢執行時物化你的表、並在其之上執行 SQL,填補了這個空缺——在 DynamoDB 訪問模式規則之內的 SQL——但對於日常的瀏覽與編輯,上面那些操作就是全部的工具箱。
常見問題
如何在不用 AWS 主控台的情況下檢視 DynamoDB 資料?
用一個發出同樣 Scan/Query 呼叫的桌面圖形介面。AWS 主控台透過分頁掃描瀏覽表;像 DynoTable 這樣的專用用戶端做同樣的事,但會顯示消耗容量和你正在執行的操作。
如何編輯一個 DynamoDB 項?
對該項的完整主索引鍵發出一次 UpdateItem,用一個 SET 更新運算式只指名你正在更改的屬性。在圖形介面裡,內聯編輯單元格——它會替你編譯成那次 UpdateItem。
為什麼篩選仍然花掉一次全表掃描的開銷? 因為 DynamoDB 是在掃描讀取項之後才應用篩選。被篩掉的項仍然被讀取並計量。要削減開銷,按分割區索引鍵(或一個 GSI)查詢,而不是掃描。
能一次更新很多項嗎?
沒有 UPDATE … WHERE——每個 UpdateItem/DeleteItem 只針對單個主索引鍵。要在一次原子請求中更改多個項,TransactWriteItems 可應用最多 100 個寫入動作(包括 Update),它們要麼全部成功,要麼全部回滾。否則你就掃描/查詢收集鍵,然後逐個寫入(每個 BatchWriteItem 最多 25 個)。
能用同樣的方式瀏覽一張 DynamoDB Local 表嗎? 能——把同一個圖形介面指向本地終端節點。參見 DynamoDB Local。
想瀏覽、篩選並內聯編輯 DynamoDB 表——還想執行 PartiQL 跑不了的 SQL 嗎?下載 DynoTable。