Qual è il modo consigliato per eliminare un numero elevato di elementi da DynamoDB?


111

Sto scrivendo un semplice servizio di registrazione in DynamoDB.

Ho una tabella dei log che è codificata da un hash user_id e un intervallo di timestamp (Unix epoch int).

Quando un utente del servizio chiude il proprio account, è necessario eliminare tutti gli elementi nella tabella, indipendentemente dal valore dell'intervallo.

Qual è il modo consigliato per eseguire questo tipo di operazione (tenendo presente che potrebbero esserci milioni di elementi da eliminare)?

Le mie opzioni, per quanto posso vedere sono:

R: Eseguire un'operazione di scansione, chiamando l'eliminazione su ogni articolo restituito, finché non vengono lasciati elementi

B: Esegui un'operazione BatchGet, chiamando di nuovo delete su ogni elemento finché non ne rimane nessuno

Entrambi mi sembrano terribili perché impiegheranno molto tempo.

Quello che idealmente voglio fare è chiamare LogTable.DeleteItem (user_id) - Senza fornire l'intervallo e fare in modo che cancelli tutto per me.

Risposte:


52

Quello che idealmente voglio fare è chiamare LogTable.DeleteItem (user_id) - Senza fornire l'intervallo e fare in modo che cancelli tutto per me.

Una richiesta davvero comprensibile; Posso immaginare operazioni avanzate come queste potrebbero essere aggiunte nel tempo dal team AWS (hanno una storia di iniziare con un set di funzionalità limitato prima e valutano le estensioni in base al feedback dei clienti), ma ecco cosa dovresti fare per evitare il costo di almeno una scansione completa:

  1. Utilizza Query anziché Scan per recuperare tutti gli elementi per user_id: funziona indipendentemente dalla chiave primaria hash / intervallo combinata in uso, perché HashKeyValue e RangeKeyCondition sono parametri separati in questa API e il primo ha come target solo il valore Attribute del componente hash del composito chiave primaria. .

    • Tieni presente che dovrai gestire la paginazione dell'API di query qui come al solito, vedere il parametro ExclusiveStartKey :

      Chiave primaria dell'elemento da cui continuare una query precedente. Una query precedente potrebbe fornire questo valore come LastEvaluatedKey se tale operazione di query è stata interrotta prima del completamento della query; a causa della dimensione del set di risultati o del parametro Limit. LastEvaluatedKey può essere restituito in una nuova richiesta di query per continuare l'operazione da quel punto.

  2. Ripeti tutti gli articoli restituiti e facilita DeleteItem come al solito

    • Aggiornamento : molto probabilmente BatchWriteItem è più appropriato per un caso d'uso come questo (vedi sotto per i dettagli).

Aggiornare

Come evidenziato da ivant , l' operazione BatchWriteItem consente di inserire o eliminare diversi elementi su più tabelle in una singola chiamata API [enfasi mia] :

Per caricare un elemento, puoi utilizzare l'API PutItem e per eliminare un elemento, puoi utilizzare l'API DeleteItem. Tuttavia, quando desideri caricare o eliminare grandi quantità di dati, come caricare grandi quantità di dati da Amazon Elastic MapReduce (EMR) o migrare dati da un altro database ad Amazon DynamoDB, questa API offre un'alternativa efficiente.

Tieni presente che questo ha ancora alcune limitazioni rilevanti, in particolare:

  • Numero massimo di operazioni in una singola richiesta : è possibile specificare un totale di un massimo di 25 operazioni di inserimento o eliminazione; tuttavia, la dimensione totale della richiesta non può superare 1 MB (il payload HTTP).

  • Operazione non atomica : le singole operazioni specificate in un BatchWriteItem sono atomiche; tuttavia BatchWriteItem nel suo insieme è un'operazione "best-effort" e non un'operazione atomica. Ovvero, in una richiesta BatchWriteItem, alcune operazioni potrebbero avere esito positivo e altre potrebbero non riuscire. [...]

Tuttavia, questo ovviamente offre un vantaggio potenzialmente significativo per casi d'uso come quello in esame.


4
Penso che avrebbe senso usare l'eliminazione batch per il secondo passaggio (è "mascherato" come un'operazione di scrittura batch )
ivant

1
@ivant - grazie mille per il suggerimento, questa funzionalità di eliminazione "mascherata" di BatchWriteItem mi è effettivamente sfuggita allora; Ho aggiornato la risposta di conseguenza.
Steffen Opel

per l'eliminazione con BatchWriteItemelementi deve essere specificato tramiteTableWriteItems
Neil

1
Il collegamento a BatchWriteItem è ora docs.aws.amazon.com/amazondynamodb/latest/APIReference/…
Tony,

3
Mi rendo conto che questo è vecchio e l'OP non ha menzionato un SDK di linguaggio specifico, ma in Python c'è un alto livello batch_writer()come parte boto3.resource.Tabledell'API che "gestirà automaticamente il buffering e l'invio di elementi in batch. Inoltre, il batch writer lo farà inoltre gestisce automaticamente tutti gli elementi non elaborati e li invia nuovamente se necessario "cioè è un wrapper attorno a BatchWriteItem che gestisce le parti fastidiose. boto3.amazonaws.com/v1/documentation/api/latest/reference/…
Davos

46

Secondo la documentazione di DynamoDB potresti semplicemente eliminare l'intera tabella.

Vedi sotto:

"L'eliminazione di un'intera tabella è notevolmente più efficiente rispetto alla rimozione di elementi uno per uno, il che sostanzialmente raddoppia la velocità di scrittura in quanto si eseguono tante operazioni di eliminazione quante operazioni put"

Se desideri eliminare solo un sottoinsieme dei tuoi dati, puoi creare tabelle separate per ogni mese, anno o simili. In questo modo potresti rimuovere "il mese scorso" e mantenere intatto il resto dei tuoi dati.

Ecco come eliminare una tabella in Java utilizzando l'SDK AWS:

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

8
Mi piace anche questa risposta ma attenzione: questo potrebbe creare molte tabelle nel tuo sistema e paghiamo per fornitura di tavoli. Pertanto, è necessario ridurre il provisioning dopo la fine del mese (se la tabella è al mese) mentre questa tabella non viene eliminata.
Sergio MC Figueiredo

2
d'accordo con questa risposta, viene applicata se è necessario eliminare tutti i record dalla tabella, ma qui l'interrogante desidera eliminare le voci di base utente non l'intera tabella.
Ihtsham Minhas

1
Avere una tabella separata per ogni utente sarebbe costoso dato il prezzo di DynamoDB. Un tavolo al mese peggiorerebbe effettivamente le cose. Questa è chiaramente una risposta per un problema diverso e molto specifico.
André Werlang,

11
Anche l'eliminazione della tabella potrebbe non essere un'opzione interessante se utilizzi il provisioning automatizzato come CloudFormation per gestire la tua tabella come parte di uno stack. Non sono a conoscenza di un modo semplice per far ricreare a CloudFormation una tabella che hai eliminato a mano.
Brabster

2
Questo approccio richiede un bel po 'di tempo per eliminare e ricreare (quando necessario) la tabella, rendendola non disponibile per tutto il tempo. La domanda afferma chiaramente la rimozione dei dati utente, che sarebbe una suddivisione poco pratica in tabelle separate per utente.
André Werlang

13

Se desideri eliminare gli elementi dopo un po 'di tempo, ad esempio dopo un mese, usa semplicemente l'opzione Time To Live. Sarà Non contare le unità di scrittura.

Nel tuo caso, aggiungerei ttl quando i log scadono e li lascerei dopo l'eliminazione di un utente. TTL si assicurerebbe che i log vengano rimossi alla fine.

Quando Time To Live è abilitato su una tabella, un processo in background controlla l'attributo TTL degli elementi per vedere se sono scaduti.

DynamoDB in genere elimina gli elementi scaduti entro 48 ore dalla scadenza. La durata esatta entro la quale un elemento viene effettivamente eliminato dopo la scadenza è specifica della natura del carico di lavoro e delle dimensioni della tabella. Gli elementi scaduti e non eliminati verranno comunque visualizzati in letture, query e scansioni. Questi elementi possono ancora essere aggiornati e gli aggiornamenti riusciti per modificare o rimuovere l'attributo di scadenza verranno rispettati.

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


l'aggiunta di TTL è un "aggiornamento" (operazione di scrittura). Non sono sicuro che ci sia alcun vantaggio per fare un "aggiornamento" invece di una "cancellazione".
Tomer

puoi avere quei dati inseriti con la scrittura originale e aggiornati con qualsiasi altra azione di aggiornamento. Ovviamente, non è un'opzione se hai un sacco di dati e poi vuoi eliminarli. Ma questa è un'opzione valida per i casi in cui puoi avere ttl per i dati che inserisci o aggiorni.
Lukas Liesis

1
Sono d'accordo, se è già configurato TTL e la pulizia può attendere fino a 48 ore, questa è sicuramente l'opzione ottimale. Mi scuso se non sono stato chiaro.
Tomer

4

La risposta a questa domanda dipende dal numero di articoli, dalle loro dimensioni e dal budget. Dipende da questo abbiamo i seguenti 3 casi:

1- Il numero di articoli e le dimensioni degli articoli nella tabella non sono molto elevati. quindi, come ha detto Steffen Opel, puoi usare Query piuttosto che Scan per recuperare tutti gli elementi per user_id e quindi scorrere tutti gli articoli restituiti e facilitareDeleteItem oBatchWriteItem. Ma tieni presente che potresti bruciare molta capacità di throughput qui. Ad esempio, considera una situazione in cui devi eliminare 1000 elementi da una tabella DynamoDB. Supponiamo che ogni elemento abbia una dimensione di 1 KB, risultando in circa 1 MB di dati. Questa attività di eliminazione in blocco richiederà un totale di 2000 unità di capacità di scrittura per la query e l'eliminazione. Per eseguire questo caricamento dei dati entro 10 secondi (che non è nemmeno considerato così veloce in alcune applicazioni), è necessario impostare il throughput di scrittura fornito della tabella su 200 unità di capacità di scrittura. Come puoi vedere, è fattibile da usare in questo modo se è per un numero inferiore di articoli o oggetti di piccole dimensioni.

2- Abbiamo molti articoli o articoli molto grandi nella tabella e possiamo memorizzarli a seconda del tempo in tabelle diverse. Quindi, come ha detto Jonathan, puoi semplicemente eliminare la tabella. questo è molto meglio ma non credo che sia abbinato al tuo caso. Poiché si desidera eliminare tutti i dati degli utenti indipendentemente dall'ora di creazione dei log, in questo caso non è possibile eliminare una tabella particolare. se vuoi avere una tabella separata per ogni utente, immagino che se il numero di utenti è alto, allora è così costoso e non è pratico per il tuo caso.

3- Se hai molti dati e non riesci a dividere i tuoi dati caldi e freddi in tabelle diverse e devi eliminare frequentemente su larga scala, sfortunatamente DynamoDB non è affatto una buona opzione per te. Potrebbe diventare più costoso o molto lento (dipende dal budget). In questi casi ti consiglio di trovare un altro database per i tuoi dati.


0

Il mio approccio per eliminare tutte le righe da una tabella in DynamoDb è semplicemente quello di estrarre tutte le righe dalla tabella, utilizzando DynamoDbs ScanAsync e quindi fornire l'elenco dei risultati a DynamoDbs AddDeleteItems. Il codice seguente in C # funziona bene per me.

        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();
    }

Nota: eliminare la tabella e quindi ricrearla di nuovo dalla console web potrebbe causare problemi se si utilizza YAML / CloudFront per creare la tabella.


0

Non abbiamo opzioni per troncare le tabelle dinamo. dobbiamo eliminare la tabella e creare di nuovo. Gli addebiti DynamoDB si basano su ReadCapacityUnits e WriteCapacityUnits. Se cancelliamo tutti gli elementi utilizzando la funzione BatchWriteItem, utilizzerà WriteCapacityUnits. Quindi è meglio eliminare record specifici o eliminare la tabella e ricominciare.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.