DynamoDBから多数のアイテムを削除するための推奨される方法は何ですか?


111

DynamoDBで簡単なロギングサービスを書いています。

user_idハッシュとタイムスタンプ(Unixエポックint)範囲をキーとするログテーブルがあります。

サービスのユーザーがアカウントを終了すると、範囲の値に関係なく、テーブル内のすべてのアイテムを削除する必要があります。

この種の操作を実行するための推奨される方法は何ですか(何百万ものアイテムが削除される可能性があることに注意してください)?

私が見る限り、私の選択肢は:

A:スキャン操作を実行し、アイテムがなくなるまで、返された各アイテムに対してdeleteを呼び出します。

B:BatchGet操作を実行し、アイテムがなくなるまで各アイテムで削除を再度呼び出します

どちらも時間がかかるので、どちらもひどく見えます。

私が理想的には、LogTable.DeleteItem(user_id)を呼び出します-範囲を指定せずに、すべてを削除してもらいます。

回答:


52

私が理想的には、LogTable.DeleteItem(user_id)を呼び出します-範囲を指定せずに、すべてを削除してもらいます。

確かに理解できる要求です。これらのような高度な操作は、AWSチームによって追加される可能性があると想像できます(これらは、限られた機能セットから始めて、顧客のフィードバックに基づいて拡張機能を評価した履歴があります)が、コストを回避するためにすべきことは次のとおりです少なくともフルスキャン:

  1. 使用クエリではなく、スキャンのために、すべてのアイテムを取得するにはuser_id-これは、結合されたハッシュに関係なく動作しますので、/、使用中の主キーの範囲HashKeyValueRangeKeyConditionは、このAPIで別々のパラメータがあり、前者はターゲットのみ複合のハッシュ要素の属性値を主キー。

    • ノートyou''llがここにいつものように、クエリAPIの呼び出しに対処する必要があること、を参照してくださいExclusiveStartKeyのパラメータを:

      以前のクエリを続行するアイテムの主キー。以前のクエリでは、クエリが完了する前にそのクエリ操作が中断された場合、この値をLastEvaluatedKeyとして提供する場合がありました。結果セットのサイズまたはLimitパラメータが原因です。LastEvaluatedKeyを新しいクエリ要求に渡して、その時点から操作を続行できます。

  2. 返されたすべてのアイテムをループし、通常どおりDeleteItemを容易にする

    • 更新:ほとんどの場合、BatchWriteItemはこのようなユースケースに適しています(詳細は以下を参照)。

更新

ivantで強調表示されているように、BatchWriteItemオペレーションを使用すると、1回のAPI呼び出しで複数のテーブルにまたがる複数のアイテムを配置または削除できます[強調]

1つのアイテムをアップロードするには、PutItem APIを使用し、1つのアイテムを削除するには、DeleteItem APIを使用できます。ただし、Amazon Elastic MapReduce(EMR)から大量のデータをアップロードしたり、別のデータベースからAmazon DynamoDBにデータを移行したりするなど、大量のデータをアップロードまたは削除する場合、このAPIは効率的な代替手段を提供します。

これには、いくつかの関連する制限があり、特に次の点に注意してください。

  • 1つのリクエストでの最大操作数 —合計で最大25のputまたはdelete操作を指定できます。ただし、リクエストの合計サイズは1 MB(HTTPペイロード)を超えることはできません。

  • アトミック操作ではありません — BatchWriteItemで指定された個々の操作はアトミックです。ただし、BatchWriteItemは全体として「ベストエフォート」操作であり、アトミック操作ではありません。つまり、BatchWriteItemリクエストでは、一部の操作が成功し、他の操作が失敗する可能性があります。[...]

それにもかかわらず、これは明らかに、目前のようなユースケースに潜在的に大きな利益をもたらします。


4
2番目のステップでバッチ削除を使用することは理にかなっていると思います(バッチ書き込み操作として「マスク」されています
ivant

1
@ivant-ヒントをありがとう、BatchWriteItemのこの「マスクされた」削除機能は確かに当時私をエスケープしました。それに応じて答えを更新しました。
Steffen Opel、

BatchWriteItemアイテムで削除する場合は、次のように指定する必要がありますTableWriteItems
Neil


3
これは古く、OPは特定の言語のSDKについて言及していませんが、PythonではAPIのbatch_writer()一部としてboto3.resource.Table「バッファリングとアイテムのバッチ送信を自動的に処理します。さらに、バッチライターはまた、未処理のアイテムを自動的に処理し、必要に応じて再送信します」。つまり、煩わしい部分を管理するBatchWriteItemのラッパーです。boto3.amazonaws.com/v1/documentation/api/latest/reference/…–
Davos

46

DynamoDBのドキュメントによれば、テーブル全体を削除できます。

下記参照:

「テーブル全体を削除することは、アイテムを1つずつ削除するよりもはるかに効率的です。これにより、書き込み操作を書き込み操作と同じ数だけ実行するので、書き込みスループットが本質的に2倍になります。」

データのサブセットのみを削除する場合は、月ごと、年ごとなどに個別のテーブルを作成できます。このようにして、「先月」を削除し、残りのデータをそのまま維持することができます。

これは、AWS SDKを使用してJavaでテーブルを削除する方法です。

DeleteTableRequest deleteTableRequest = new DeleteTableRequest()
  .withTableName(tableName);
DeleteTableResult result = client.deleteTable(deleteTableRequest);

8
私もこの回答が好きですが、注意してください。これにより、システム内に多くのテーブルが作成される可能性があり、テーブルごとのプロビジョニングに対して支払います。そのため、このテーブルが削除されていない間は、月末(テーブルが月単位の場合)後にプロビジョニングを減らす必要があります。
セルジオMCフィゲイレド2014

2
この回答に同意します。テーブルからすべてのレコードを削除する必要がある場合に適用されますが、ここでは質問者がテーブル全体ではなくユーザーベースのエントリを削除したいと考えています。
Ihtsham Minhas

1
ユーザーごとに個別のテーブルテーブルを用意すると、DynamoDBの価格を考えるとコストがかかります。1か月に1つのテーブルは、実際には事態を悪化させます。これは明らかに、別の非常に具体的な問題に対する答えです。
アンドレ・Werlang

11
CloudFormationなどの自動プロビジョニングを使用してテーブルをスタックの一部として管理している場合も、テーブルを削除することは魅力的なオプションではありません。CloudFormationが手動で削除したテーブルを再作成する簡単な方法は知りません。
ブラブスター2017年

2
この方法では、テーブルを削除して(必要に応じて)再作成するのにかなりの時間がかかり、その間はテーブルを使用できなくなります。質問は明らかにユーザーデータの削除を示していますが、これはユーザーごとの個別のテーブルに分割することは現実的ではありません。
アンドレ・Werlang

13

1か月後など、しばらくしてからアイテムを削除する場合は、有効期間オプションを使用します。書き込み単位カウントされません

あなたの場合、ログが期限切れになったときにttlを追加し、ユーザーが削除された後は残しておきます。TTLは、ログが最終的に削除されることを確認します。

テーブルでTime To Liveが有効になっている場合、バックグラウンドジョブはアイテムのTTL属性をチェックして、アイテムが期限切れかどうかを確認します。

DynamoDBは通常、期限切れから48時間以内に期限切れのアイテムを削除します。期限切れ後にアイテムが本当に削除される正確な期間は、ワークロードの性質とテーブルのサイズによって異なります。期限切れで削除されていないアイテムは、読み取り、クエリ、スキャンに引き続き表示されます。これらのアイテムは引き続き更新でき、有効期限属性を変更または削除するための正常な更新が適用されます。

https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/howitworks-ttl.html


TTLの追加は「更新」(書き込み操作)です。「削除」の代わりに「更新」を行うことの利点があるかどうかはわかりません。
Tomer

そのデータを元の書き込みで挿入し、他の更新アクションで更新することができます。もちろん、大量のデータがあり、それを削除したい場合は、オプションではありません。ただし、これは、挿入または更新するデータにttlを使用できる場合に有効なオプションです。
Lukas Liesis、

1
すでにTTLが構成されていて、クリーンアップが最大48時間待機できる場合は、これが間違いなく最適なオプションです。不明な点があれば申し訳ありません。
Tomer

4

この質問の答えは、アイテムの数とサイズ、および予算によって異なります。それに応じて、次の3つのケースがあります。

1-表の項目の数と項目のサイズはそれほど多くありません。その後、Steffen Opelが言ったように、スキャンではなくクエリを使用してuser_idのすべてのアイテムを取得し、返されたすべてのアイテムをループして、簡単にするかDeleteItemBatchWriteItem。ただし、ここでは大量のスループット容量を消費する可能性があることに注意してください。たとえば、DynamoDBテーブルから1000アイテムを削除する必要がある状況を考えます。各アイテムのサイズが1 KBで、約1MBのデータになると想定します。この一括削除タスクでは、クエリと削除に合計2000の書き込み容量ユニットが必要になります。このデータロードを10秒以内に実行するには(一部のアプリケーションではそれほど高速とは見なされません)、テーブルのプロビジョニングされた書き込みスループットを200書き込みキャパシティーユニットに設定する必要があります。ご覧のとおり、アイテムの数が少ない場合やサイズの小さいアイテムの場合は、この方法を使用して実行できます。

2-テーブルに大量のアイテムまたは非常に大きなアイテムがあり、それらを時間に応じて別のテーブルに格納できます。次に、ジョナサンが言ったように、テーブルを削除できます。これははるかに良いですが、あなたのケースにマッチするとは思いません。ログの作成時刻に関係なく、すべてのユーザーデータを削除したいので、この場合、特定のテーブルを削除することはできません。ユーザーごとに個別のテーブルが必要な場合は、ユーザー数が多い場合は高額になるため、実際的ではありません。

3-大量のデータがあり、ホットデータとコールドデータを異なるテーブルに分割することができず、頻繁に大規模な削除を行う必要がある場合、残念ながらDynamoDBはまったく適切なオプションではありません。それはより高価になるか非常に遅くなるかもしれません(あなたの予算に依存します)。このような場合は、データ用に別のデータベースを見つけることをお勧めします。


0

DynamoDbのテーブルからすべての行を削除する私のアプローチは、DynamoDbs ScanAsyncを使用してテーブルからすべての行を引き出し、結果リストをDynamoDbs AddDeleteItemsにフィードすることです。以下のC#のコードは私にとってはうまく機能します。

        public async Task DeleteAllReadModelEntitiesInTable()
    {
        List<ReadModelEntity> readModels;

        var conditions = new List<ScanCondition>();
        readModels = await _context.ScanAsync<ReadModelEntity>(conditions).GetRemainingAsync();

        var batchWork = _context.CreateBatchWrite<ReadModelEntity>();
        batchWork.AddDeleteItems(readModels);
        await batchWork.ExecuteAsync();
    }

注:テーブルを削除してからWebコンソールから再度作成すると、YAML / CloudFrontを使用してテーブルを作成すると問題が発生する可能性があります。


0

ダイナモテーブルを切り捨てるオプションはありません。テーブルを削除して、もう一度作成する必要があります。DynamoDBの料金は、ReadCapacityUnitsとWriteCapacityUnitsに基づいています。BatchWriteItem関数を使用してすべてのアイテムを削除すると、WriteCapacityUnitsが使用されるため、特定のレコードを削除するか、テーブルを削除してからやり直してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.