J'écris un service de journalisation simple dans DynamoDB.
J'ai une table de journaux qui est indexée par un hachage user_id et une plage d'horodatage (Unix Epoch int).
Lorsqu'un utilisateur du service termine son compte, je dois supprimer tous les éléments du tableau, quelle que soit la valeur de la plage.
Quelle est la méthode recommandée pour effectuer ce type d'opération (en gardant à l'esprit qu'il pourrait y avoir des millions d'éléments à supprimer)?
Mes options, autant que je peux voir sont:
A: Effectuer une opération d'analyse en appelant delete sur chaque élément renvoyé jusqu'à ce qu'il ne reste plus d'éléments
B: Effectuer une opération BatchGet, en appelant à nouveau delete sur chaque élément jusqu'à ce qu'il n'en reste plus
Les deux me paraissent terribles, car ils prendront beaucoup de temps.
Ce que je veux idéalement faire est d'appeler LogTable.DeleteItem (user_id) - Sans fournir la plage et le faire tout effacer pour moi.
Ce que je veux idéalement faire est d'appeler LogTable.DeleteItem (user_id) - Sans fournir la gamme, et la faire tout effacer pour moi.
Une demande compréhensible en effet; Je peux imaginer des opérations avancées telles que celles-ci pourraient être ajoutées au fil du temps par l'équipe AWS (elles ont l'habitude de commencer avec un ensemble de fonctionnalités limité et d'évaluer les extensions en fonction des commentaires des clients), mais voici ce que vous devriez faire pour éviter le coût de un scan complet au moins:
Utilisez Query plutôt que Scan pour récupérer tous les éléments pour user_id
- cela fonctionne quelle que soit la clé primaire combinée de hachage/plage utilisée, car HashKeyValue et RangeKeyCondition sont des paramètres distincts cette API et la précédente ne ciblent que la valeur Attribut du composant de hachage de la clé primaire composite..
Clé primaire de l'élément à partir duquel poursuivre une requête précédente. Un requête précédente peut fournir cette valeur comme LastEvaluatedKey si cela l'opération de requête a été interrompue avant la fin de la requête; non plus en raison de la taille de l'ensemble de résultats ou du paramètre Limit. Le LastEvaluatedKey peut être renvoyé dans une nouvelle demande de requête pour continuer l'opération à partir de ce point.
Boucle sur tous les articles retournés et facilite DeleteItem comme d'habitude
Comme souligné par ivant , le BatchWriteItem operation vous permet de placer ou de supprimer plusieurs éléments de plusieurs tables dans un seul appel d'API [emphasis mine]:
Pour télécharger un élément, vous pouvez utiliser l'API PutItem et en supprimer un élément, vous pouvez utiliser l’API DeleteItem. Cependant, lorsque vous souhaitez télécharger ou supprimez de grandes quantités de données, telles que le téléchargement de grandes quantités de les données de Amazon Elastic MapReduce (EMR) ou migrez les données d'un autre base de données dans Amazon DynamoDB, cette API offre un fichier .__ efficace. alternative.
Veuillez noter que cela a encore quelques limitations pertinentes, notamment:
Nombre maximal d'opérations dans une seule demande - Vous pouvez spécifier jusqu'à 25 opérations de mise en place ou de suppression. Cependant, la taille totale de la demande ne peut pas dépasser 1 Mo (la charge HTTP).
Pas une opération atomique - Les opérations individuelles spécifiées dans un BatchWriteItem sont atomiques; Cependant, BatchWriteItem dans son ensemble est une opération "au mieux" et non une opération atomique. C'est-à-dire que dans une demande BatchWriteItem, certaines opérations peuvent réussir et d'autres peuvent échouer. [...]
Néanmoins, cela offre évidemment un gain potentiellement important pour les cas d'utilisation comme celui qui nous occupe.
Selon la documentation DynamoDB, vous pouvez simplement supprimer le tableau complet.
Voir ci-dessous:
"La suppression d'une table entière est nettement plus efficace que la suppression d'éléments un par un, ce qui double le débit en écriture en effectuant autant d'opérations de suppression que d'opérations de vente"
Si vous souhaitez supprimer uniquement un sous-ensemble de vos données, vous pouvez créer des tableaux distincts pour chaque mois, année ou similaire. De cette façon, vous pouvez supprimer "le mois dernier" et conserver le reste de vos données intact.
Voici comment supprimer une table en Java à l'aide du kit AWS SDK:
DeleteTableRequest deleteTableRequest = new DeleteTableRequest()
.withTableName(tableName);
DeleteTableResult result = client.deleteTable(deleteTableRequest);
Si vous souhaitez supprimer des éléments après un certain temps, par exemple après un mois, utilisez simplement l'option Time To Live. Pas comptera les unités d'écriture.
Dans votre cas, j'ajouterais ttl à l'expiration des journaux et laisserais ceux-ci après la suppression d'un utilisateur. TTL s'assurerait que les journaux sont éventuellement supprimés.
Lorsque Time To Live est activé sur une table, un travail en arrière-plan vérifie le fichier TTL attribut des éléments pour voir s'ils ont expiré.
DynamoDB supprime généralement les éléments expirés dans les 48 heures suivant le expiration. La durée exacte au cours de laquelle un élément est vraiment supprimé après expiration est spécifique à la nature de la charge de travail et du taille de la table. Les éléments qui ont expiré et qui n'ont pas été supprimés seront apparaissent toujours dans les lectures, les requêtes et les analyses. Ces articles peuvent encore être mises à jour et mises à jour réussies pour modifier ou supprimer l'expiration attribut sera honoré.
https://docs.aws.Amazon.com/amazondynamodb/latest/developerguide/TTL.htmlhttps://docs.aws.Amazon.com/amazondynamodb/latest/developerguide/howitworks- ttl.html
La réponse à cette question dépend du nombre d'éléments, de leur taille et de votre budget. Cela dépend des 3 cas suivants:
1- Le nombre d'éléments et la taille des éléments du tableau ne sont pas très importants. Ensuite, comme Steffen Opel a déclaré, vous pouvez utiliser la requête plutôt que le balayage pour récupérer tous les éléments pour user_id, puis les parcourir tous les éléments et faciliter soit DeleteItem
ou BatchWriteItem
. Mais gardez à l’esprit que vous pouvez utiliser beaucoup de capacité de traitement ici. Par exemple, considérons une situation dans laquelle vous devez supprimer 1000 éléments d'une table DynamoDB. Supposons que chaque élément ait une taille de 1 Ko, ce qui donne environ 1 Mo de données. Cette tâche de suppression en bloc nécessitera un total de 2000 unités de capacité d'écriture pour la requête et la suppression. Pour effectuer ce chargement de données dans les 10 secondes (ce qui n'est même pas considéré comme rapide dans certaines applications), vous devez définir le débit en écriture provisionné de la table sur 200 unités de capacité en écriture. Comme vous pouvez le voir, il est possible de l’utiliser de cette manière si son nombre d’articles ou d’articles de petite taille est réduit.
2- Nous avons beaucoup d'articles ou de très gros articles dans la table et nous pouvons les stocker en fonction de l'heure dans différentes tables. Ensuite, comme Jonathan dit que vous pouvez simplement supprimer la table. c'est beaucoup mieux, mais je ne pense pas que cela corresponde à votre cas. Comme vous voulez supprimer toutes les données des utilisateurs, quelle que soit l'heure de la création des journaux, vous ne pouvez pas supprimer un tableau particulier. si vous voulez avoir une table séparée pour chaque utilisateur, alors je suppose que si le nombre d'utilisateurs est élevé, alors c'est tellement cher et ce n'est pas pratique pour votre cas.
3- Si vous avez beaucoup de données et que vous ne pouvez pas diviser vos données chaudes et froides en différentes tables et que vous devez supprimer fréquemment à grande échelle, malheureusement, DynamoDB n'est pas une bonne option pour vous. Cela peut devenir plus coûteux ou très lent (cela dépend de votre budget). Dans ces cas, je vous recommande de rechercher une autre base de données pour vos données.
Nous n'avons pas l'option de tronquer les tables de dynamo. nous devons laisser tomber la table et créer à nouveau. DynamoDB Charges est basé sur ReadCapacityUnits & WriteCapacityUnits. Si nous supprimons tous les éléments à l'aide de la fonction BatchWriteItem, il utilisera WriteCapacityUnits. Il est donc préférable de supprimer des enregistrements spécifiques ou de supprimer la table et de recommencer.
Mon approche pour supprimer toutes les lignes d'une table dans DynamoDb consiste simplement à extraire toutes les lignes de la table, en utilisant DynamoDbs ScanAsync, puis en alimentant la liste de résultats dans DynamoDbs AddDeleteItems. Le code ci-dessous en C # me convient parfaitement.
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();
}
Remarque: la suppression de la table, puis sa recréation à partir de la console Web peuvent poser des problèmes si vous utilisez YAML/CloudFront pour créer la table.