DynamoDBで簡単なロギングサービスを作成しています。
User_idハッシュとタイムスタンプ(Unix Epoch int)範囲をキーとするログテーブルがあります。
サービスのユーザーがアカウントを終了すると、範囲の値に関係なく、テーブル内のすべてのアイテムを削除する必要があります。
この種の操作を行うための推奨される方法は何ですか(削除するアイテムが数百万ある可能性があることに留意してください)?
私が見る限り、私のオプションは次のとおりです。
A:スキャン操作を実行し、返される各アイテムでdeleteを呼び出し、アイテムがなくなるまで
B:BatchGet操作を実行し、残りがなくなるまで各アイテムでdeleteを再度呼び出します
これらは両方とも時間がかかるので、私には恐ろしく見えます。
私が理想的にしたいのは、LogTable.DeleteItem(user_id)を呼び出すことです-範囲を指定せずに、すべてを削除してください。
私が理想的にしたいのは、LogTable.DeleteItem(user_id)を呼び出すことです-範囲を指定せずに、すべてを削除してください。
実際に理解できる要求。これらのような高度な操作は、AWSチームによって時間の経過とともに追加される可能性があります(最初は限られた機能セットから開始し、顧客のフィードバックに基づいて拡張機能を評価した歴史があります)が、コストを回避するためにすべきこと少なくともフルスキャン:
Scan ではなく Query を使用して、user_id
のすべてのアイテムを取得します。これは、 HashKeyValueとRangeKeyConditionはこのAPIの個別のパラメーターであり、前者はのハッシュコンポーネントのAttribute値のみを対象とするため複合主キー。。
以前のクエリを続行するアイテムの主キー。以前のクエリでは、クエリを完了する前にクエリ操作が中断された場合、この値がLastEvaluatedKeyとして提供されます。結果セットのサイズまたはLimitパラメーターが原因です。 LastEvaluatedKeyを新しいクエリリクエストに返して、その時点から操作を続行できます。
返されたすべてのアイテムをループし、通常どおり DeleteItem を促進します
ivant で強調表示されているように、 BatchWriteItem 操作を使用すると、またはdelete 単一のAPI呼び出しで複数のテーブルにまたがるいくつかのアイテム[強調マイン]:
1つのアイテムをアップロードするにはPutItem APIを使用し、1つのアイテムを削除するにはDeleteItem APIを使用できます。ただし、Amazon Elastic MapReduce(EMR)から大量のデータをアップロードしたり、別のデータベースからAmazon DynamoDBにデータを移行するなど、大量のデータをアップロードまたは削除する場合、このAPIは効率的な代替手段を提供します。
これにはいくつかの関連する制限がありますが、特に注目すべき点に注意してください。
単一のリクエストでの最大操作—合計で最大25のputまたはdelete操作を指定できます。ただし、リクエストの合計サイズは1 MB(HTTPペイロード)を超えることはできません。
アトミック操作ではありません— BatchWriteItemで指定された個々の操作はアトミックです。ただし、BatchWriteItem全体は、「ベストエフォート」操作であり、アトミック操作ではありません。つまり、BatchWriteItemリクエストでは、一部の操作が成功し、他の操作が失敗する場合があります。 [...]
それにもかかわらず、これは明らかに手元のようなユースケースにとって潜在的に重要な利益を提供します。
DynamoDBのドキュメントによると、テーブル全体を削除するだけで済みます。
下記参照:
「テーブル全体を削除することは、アイテムを1つずつ削除するよりもはるかに効率的です。これは、書き込み操作をプット操作と同じ数だけ削除するので、基本的に書き込みスループットが2倍になります」
データのサブセットのみを削除する場合は、月、年などごとに個別のテーブルを作成できます。これにより、「先月」を削除し、残りのデータをそのまま保持できます。
これは、AWS SDKを使用してJavaのテーブルを削除する方法です。
DeleteTableRequest deleteTableRequest = new DeleteTableRequest()
.withTableName(tableName);
DeleteTableResult result = client.deleteTable(deleteTableRequest);
しばらくしてからアイテムを削除する場合、たとえば1か月後、Time To Liveオプションを使用します。書き込み単位を数えますnot。
あなたの場合、ログの有効期限が切れたときにttlを追加し、ユーザーが削除された後にログを残します。 TTLは、ログが最終的に削除されることを確認します。
テーブルでTime To Liveが有効になっている場合、バックグラウンドジョブは、アイテムのTTL属性をチェックして、期限切れかどうかを確認します。
DynamoDBは通常、有効期限の48時間以内に期限切れのアイテムを削除します。有効期限が切れた後にアイテムが本当に削除される正確な期間は、ワークロードの性質とテーブルのサイズに固有です。期限切れで削除されていないアイテムは、読み取り、クエリ、スキャンに引き続き表示されます。これらの項目は引き続き更新でき、有効期限属性を変更または削除するための正常な更新は受け入れられます。
https://docs.aws.Amazon.com/amazondynamodb/latest/developerguide/TTL.htmlhttps://docs.aws.Amazon.com/amazondynamodb/latest/developerguide/ howitworks-ttl.html
この質問の答えは、アイテムの数とそのサイズ、および予算によって異なります。それに応じて、次の3つのケースがあります。
1-テーブル内のアイテムの数とアイテムのサイズはそれほど多くありません。次に、Steffen Opelが言ったように、スキャンではなくクエリを使用してuser_idのすべてのアイテムを取得し、返されたすべてのアイテムをループして、DeleteItem
またはBatchWriteItem
を促進できます。ただし、ここで多くのスループット容量を消費する可能性があることに注意してください。たとえば、DynamoDBテーブルから1000アイテムを削除する必要がある状況を考えます。各アイテムのサイズが1 KBであり、結果として約1 MBのデータになると仮定します。この一括削除タスクでは、クエリと削除に合計2000の書き込みキャパシティーユニットが必要です。このデータロードを10秒以内に実行するには(一部のアプリケーションでは高速とは見なされていません)、テーブルのプロビジョニングされた書き込みスループットを200書き込み容量単位に設定する必要があります。ご覧のとおり、アイテム数が少ない場合やサイズの小さいアイテムの場合は、この方法を使用することができます。
2-テーブルには多くのアイテムまたは非常に大きなアイテムがあり、それらを時間に応じて異なるテーブルに保存できます。その後、ジョナサンが言ったように、テーブルを削除するだけです。これははるかに優れていますが、あなたのケースと一致するとは思いません。ログの作成時刻に関係なくすべてのユーザーデータを削除するため、この場合は特定のテーブルを削除できません。ユーザーごとに個別のテーブルが必要な場合、ユーザー数が多い場合は非常に高価であり、あなたの場合には実用的ではないと思います。
3-大量のデータがあり、ホットデータとコールドデータを異なるテーブルに分割できず、大規模な削除を頻繁に行う必要がある場合、残念ながらDynamoDBはまったく良い選択肢ではありません。より高価になるか、非常に遅くなる場合があります(予算によって異なります)。これらの場合、データ用の別のデータベースを見つけることをお勧めします。
ダイナモテーブルを切り捨てるオプションはありません。テーブルを削除して再度作成する必要があります。 DynamoDB料金は、ReadCapacityUnitsおよびWriteCapacityUnitsに基づいています。 BatchWriteItem関数を使用してすべての項目を削除する場合、WriteCapacityUnits.Soを使用して、特定のレコードを削除するか、テーブルを削除してからやり直します。
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を使用してテーブルを作成する場合に問題が発生する可能性があります。