入門閱讀時間 2 分鐘

如何在 DynamoDB 中刪除多個項

DynamoDB 中沒有 DELETE FROM table WHERE …。每一次刪除都針對由完整主索引鍵標識的一個項——API 沒有批次刪除操作,沒有 truncate,而 DELETE 語句每條也只刪除恰好一個項。所以"刪除多個項"永遠是一個兩步的活兒:先找到鍵,再對每個鍵發出一次刪除,併為了吞吐量打包成批。

本指南涵蓋各種批次選項、全有或全無的事務變體、刪光整張表的場景,以及如何在圖形介面裡用一次選擇加兩個快捷鍵做同樣的事。

如何在 DynamoDB 中刪除多個項?

先收集你想刪掉的項的主索引鍵(透過 QueryScan),然後分批刪除:BatchWriteItem 每次呼叫最多接受 25 個 DeleteRequestTransactWriteItems 原子地刪除最多 100 個項,而 PartiQL 的 DELETE 語句可以用 BatchExecuteStatement 按每批 25 條批次執行。在 DynoTable 裡,你選中行並按 ⌘⌫ 暫存這些刪除,然後審閱並提交。

第 0 步:收集鍵

一次刪除需要完整的主索引鍵——在一張 表上,那就是分割區索引鍵_和_排序索引鍵(AWS:"對於每個主索引鍵,你必須提供_所有_的鍵屬性")。你無法按任意屬性刪除,所以"刪除所有 status = 'archived' 的項"要從一次讀取開始:

  • 如果條件落在某個鍵(或某個 GSI 的鍵)上,一次有針對性的 Query 就能廉價地收集到鍵。
  • 否則就是一次帶篩選的 Scan——不管有沒有篩選,它都會讀取(並計費)整張表;參見 Query 與 Scan

用一個只返回鍵屬性的 ProjectionExpression,並沿著 LastEvaluatedKey 一路翻到底(分頁),否則你會悄無聲息地只刪掉第一個 1 MB 頁裡的那部分。

方法 1:BatchWriteItem(每次呼叫最多 25 個刪除)

BatchWriteItem 把最多 25 個 put/delete 請求或 16 MB 打成一次呼叫(AWS API 參考:"一次 BatchWriteItem 呼叫最多可透過網路傳輸 16MB 資料,其中包含最多 25 個項的 put 或 delete 操作")。

aws dynamodb batch-write-item --request-items '{
  "Orders": [
    {"DeleteRequest": {"Key": {"PK": {"S": "ORDER#1001"}, "SK": {"S": "META"}}}},
    {"DeleteRequest": {"Key": {"PK": {"S": "ORDER#1002"}, "SK": {"S": "META"}}}},
    {"DeleteRequest": {"Key": {"PK": {"S": "ORDER#1003"}, "SK": {"S": "META"}}}}
  ]
}'

批次有三個常絆倒人的性質——全都直接出自 API 參考

  • 它不是原子的。"BatchWriteItem 中指定的各個 PutItemDeleteItem 操作是原子的;但 BatchWriteItem 作為一個整體不是。"有些刪除可能落地而另一些沒有。
  • 你必須重試 UnprocessedItems被限流的請求會以與請求相同的形狀出現在響應的 UnprocessedItems 對映中——"通常,你會在一個迴圈中呼叫 BatchWriteItem",而且 AWS"強烈建議你在重試之間使用指數退避演算法"。
  • 不支援條件。"你不能在單個 put 和 delete 請求上指定條件"——條件刪除只能改走 DeleteItem 或事務。一個批次也拒絕在同一次呼叫裡對同一個鍵執行兩個操作。

這個迴圈的形狀——按 25 分塊、傳送、把剩餘的帶退避重新排隊——與 批次操作 中講的是同一個。

方法 2:TransactWriteItems(原子刪除)

當一組刪除必須一起成功或失敗時——比如移除一個父項及其 子項——用 TransactWriteItems:最多 100 個動作(刪除、put、更新、條件檢查)原子地應用,且允許逐項的 。代價是:一次事務寫入花費普通寫入兩倍的寫入容量。完整機制(冪等 token、TransactionCanceledException、成本計算)在 DynamoDB 事務

方法 3:PartiQL DELETE,批次執行

PartiQL 並沒有解除按鍵規則——它只是換了個拼法。開發者指南說得很明確(PartiQL DELETE):"一次只能刪除一個項。你不能發出一條刪除多個項的 DynamoDB PartiQL 語句",而且 WHERE 條件"必須解析為單個主索引鍵值"。

要刪除多個項,你就批次執行單項語句——BatchExecuteStatement 每批最多執行 25 條語句(全部是讀或全部是寫,絕不混合):

[
  {"Statement": "DELETE FROM \"Orders\" WHERE PK = 'ORDER#1001' AND SK = 'META'"},
  {"Statement": "DELETE FROM \"Orders\" WHERE PK = 'ORDER#1002' AND SK = 'META'"}
]
aws dynamodb batch-execute-statement --statements file://statements.json

一個沒有釘死完整鍵的 WHERE 會失敗——不存在 DELETE FROM Orders WHERE status = 'archived'。更多 PartiQL 模式(及其背後的限制)見 PartiQL 示例PartiQL 與 SQL

刪除所有項(truncate)

DynamoDB 沒有 truncate。你的選項,按優先順序:

  1. 刪除並重建表。逐項刪除整張表要為每個項付一次寫入;DeleteTable + CreateTable 則完全繞開了這筆寫入賬單。代價是:表設定——索引、TTL、、容量模式、標籤——不會自己回來;你要在建立時重新宣告它們(有基礎設施即程式碼這就不算個事)。
  2. 讓項過期。如果你真正想要的是"刪除所有早於 X 的東西",TTL 會在後臺刪除過期項,且不消耗寫入容量——一場慢動作的批次刪除,分文不花。
  3. Scan + 批次刪除方法 1),當表必須保持線上且只刪一個子集時——你為掃描到的每個項付一次讀取,再為刪除的每個項付一次寫入。

在 DynoTable 中刪除多個項

上面那套先選後刪的流程——查詢、收集鍵、分塊、重試——正是圖形介面應該替你包攬的雜活。在 DynoTable 裡它就是一次網格選擇:

  1. 執行或篩選一個查詢,讓你想刪掉的行出現在螢幕上。
  2. 選中它們並按 ⌘⌫——每個被選中的行都變成一個暫存刪除。此時還沒有任何東西碰到 DynamoDB:這些行在網格中染成紅色,並作為可審閱的卡片出現在暫存面板中。
  3. 審閱,然後提交。提交以 TransactWriteItems 批次發出,並帶樂觀鎖條件——一個暫存刪除只有在該項仍然存在時才會執行——大的暫存批次會自動分塊,以保持在 DynamoDB 的事務限制之內。⌘⇧⌫ 跳過審閱,用一個和絃把選擇直接刪除並提交。
DynoTable 中的暫存刪除:選中的行在網格中染成紅色,每一行都是提交前暫存面板裡一張可審閱的卡片。
DynoTable 中的暫存刪除:選中的行在網格中染成紅色,每一行都是提交前暫存面板裡一張可審閱的卡片。

作用範圍是誠實的:你刪除的是你選中的行——一次經過審閱、提交前可反悔的操作——而不是一次盲目的全表 truncate。要清空整張表,刪掉並重建它(見上文)。

如果某次刪除需要手寫條件(attribute_exists、版本檢查),在 DynamoDB 運算式構建器 中構建精確的 ConditionExpression + 預留位置對映,把它掛到一次 DeleteItem 或事務上。

常見問題

能在一次 DynamoDB 呼叫中刪除多個項嗎? 能——用 BatchWriteItem 最多 25 個(盡力而為,重試 UnprocessedItems),或用 TransactWriteItems 原子地刪除最多 100 個。兩者都要求每個項給出完整主索引鍵;都不接受用"where"條件來選擇項。

DynamoDB 有 DELETE WHERE 嗎? 沒有。低階 API 和 PartiQL 都無法按條件刪除——PartiQL 的 DELETE 要求一個"解析為單個主索引鍵值"的 WHERE。你先查詢或掃描出鍵,然後逐個刪除。

如何刪除一張 DynamoDB 表裡的所有項? 要整表清空,刪除並重建表——這避免了為每個項付一次寫入。要做基於時間的清理,用 TTL,它刪除過期項且不消耗寫入容量。當表必須保持線上時,Scan + 批次刪除是兜底方案。

為什麼批次刪除之後項又出現了? 幾乎總是沒有重試的 UnprocessedItems:被限流的 BatchWriteItem 會把失敗的刪除悄悄放回響應裡,而不對它們迴圈重試的程式碼會在表裡還剩著項的情況下就"完成"了。用指數退避重試,直到那個對映回來是空的。

刪除項要花多少錢? 每次刪除是一次標準寫入(每 1 KB 一個 WCU,事務內翻倍),找鍵本身也要花讀取。用定價計算器估算這筆開銷。

想先看清你要刪的是什麼?下載 DynoTable——選中行,用 ⌘⌫ 暫存刪除,審閱差異,確定之後再提交。

已更新