2013-04-12 5 views
18

Esiste un modo efficace per eliminare tutti gli elementi da una tabella dinamodb di Amazon contemporaneamente. Ho esaminato i documenti di aws, ma è stata visualizzata l'eliminazione di un singolo elemento.Eliminazione da amazon dynamodb

+0

Puoi semplicemente eliminare la tabella? Altrimenti, questo potrebbe aiutare: http://stackoverflow.com/questions/9154264/questo-è-il-recomended-way-to-delete-a-large-number-of-items-from-dynamodb – alfredaday

+0

Grazie alfredaday !! !! ma ogni volta che cancelli e crei una stessa tabella creerai un sovraccarico nella mia app ... – rampuriyaaa

+1

Inoltre, la creazione di tabelle non è istantanea. Assicurati di non scrivere sulla nuova tabella fino a quando il suo stato (leggi tramite describeTable) è "ATTIVO" –

risposta

2

Si desidera utilizzare BatchWriteItem se non è possibile rilasciare la tabella. Se tutte le voci sono all'interno di un singolo HashKey, è possibile utilizzare l'API Query per recuperare i record e quindi eliminarli 25 elementi alla volta. In caso contrario, probabilmente dovrai eseguire la scansione.

In alternativa, è possibile fornire un semplice wrapper attorno allo AmazonDynamoDBClient (dall'SDK ufficiale) che raccoglie un insieme di chiavi Hash/Intervallo presenti nella tabella. Quindi non avresti bisogno di Query o Scan per gli elementi che hai inserito dopo il test, dal momento che avresti già creato il Set. Che sarebbe simile a questa:

public class KeyCollectingAmazonDynamoDB implements AmazonDynamoDB 
{ 
    private final AmazonDynamoDB delegate; 
    // HashRangePair is something you have to define 
    private final Set<Key> contents; 

    public InsertGatheringAmazonDynamoDB(AmazonDynamoDB delegate) 
    { 
     this.delegate = delegate; 
     this.contents = new HashSet<>(); 
    } 

    @Override 
    public PutItemResult putItem(PutItemRequest putItemRequest) 
      throws AmazonServiceException, AmazonClientException 
    { 
     contents.add(extractKey(putItemRequest.getItem())); 
     return delegate.putItem(putItemRequest); 
    } 

    private Key extractKey(Map<String, AttributeValue> item) 
    { 
     // TODO Define your hash/range key extraction here 
     // Create a Key object 
     return new Key(hashKey, rangeKey); 
    } 

    @Override 
    public DeleteItemResult deleteItem(DeleteItemRequest deleteItemRequest) 
      throws AmazonServiceException, AmazonClientException 
    { 
     contents.remove(deleteItemRequest.getKey()); 
     return delegate.deleteItem(deleteItemRequest); 
    } 

    @Override 
    public BatchWriteItemResult batchWriteItem(BatchWriteItemRequest batchWriteItemRequest) 
      throws AmazonServiceException, AmazonClientException 
    { 
     // Similar extraction, but in bulk. 
     for (Map.Entry<String, List<WriteRequest>> entry : batchWriteItemRequest.getRequestItems().entrySet()) 
     { 
      String tableName = entry.getKey(); 
      List<WriteRequest> writeRequests = entry.getValue(); 
      for (WriteRequest writeRequest : writeRequests) 
      { 
       PutRequest putRequest = writeRequest.getPutRequest(); 
       if (putRequest != null) 
       { 
        // Add to Set just like putItem 
       } 
       DeleteRequest deleteRequest = writeRequest.getDeleteRequest(); 
       if (deleteRequest != null) 
       { 
        // Remove from Set just like deleteItem 
       } 
      } 
     } 

     // Write through to DynamoDB 
     return delegate.batchWriteItem(batchWriteItemRequest); 
    } 

    // remaining methods elided, since they're direct delegation 
} 

Key è una classe all'interno del DynamoDB SDK che accetta zero, uno, o due AttributeValue oggetti nel costruttore di rappresentare una chiave hash o una chiave hash/intervallo. Supponendo che si tratti dei metodi equals e , è possibile utilizzarli all'interno dello Set che ho descritto. Se non lo fanno, dovrai scrivere la tua classe Key.

Questo dovrebbe ottenere un set mantenuto per l'uso nei test. Non è specifico per una tabella, quindi potresti dover aggiungere un altro livello di raccolta se utilizzi più tabelle. Ciò cambierebbe Set<Key> in qualcosa come Map<TableName, Set<Key>>. Dovresti esaminare la proprietà getTableName() per scegliere l'Set corretto da aggiornare.

Una volta terminato il test, afferrare il contenuto della tabella e eliminarlo dovrebbe essere semplice.

Un ultimo suggerimento: utilizzare una tabella diversa per i test di quanto non si faccia per la propria applicazione. Crea uno schema identico, ma dai un nome diverso alla tabella. Probabilmente vorresti anche un altro utente IAM per impedire al tuo codice di test di accedere alla tua tabella di produzione. Se hai domande a riguardo, sentiti libero di aprire una domanda a parte per quello scenario.

+1

l'approccio potrebbe essere utile per cancellare i dati del test, ma non è l'ideale per i dati reali, specialmente quando è ridimensionato. È come mantenere e gestire un altro datastore di chiavi sopra ogni tabella DynamoDB. – ps2010

5

DynamoDBMapper farà il lavoro in poche righe:

AWSCredentials credentials = new PropertiesCredentials(credentialFile); 
client = new AmazonDynamoDBClient(credentials); 
DynamoDBMapper mapper = new DynamoDBMapper(this.client); 
DynamoDBScanExpression scanExpression = new DynamoDBScanExpression(); 
PaginatedScanList<LogData> result = mapper.scan(LogData.class, scanExpression); 
for (LogData data : result) { 
    mapper.delete(data); 
} 
+0

'scan' è piuttosto costoso; tuttavia, l'uso di 'query' non è così semplice come l'API delle chiamate – Neil

12

effettuare le seguenti operazioni:

  1. Marchio eliminare richiesta tavolo
  2. Nella risposta si otterrà il TableDescription
  3. Utilizzando TableDescription crea nuovamente la tabella.

For step 1 and 2 click here

for step 3 click here

Questo è quello che faccio nella mia applicazione.

+0

DeleteTableRequest deleteTableRequest = new DeleteTableRequest() .withTableName (" myTable "); Risultato DeleteTableResult = client.deleteTable (deleteTableRequest); –

4

Solo per la cronaca, una soluzione rapida con voce per voce Elimina nel Python 3 (usando Boto3 e scansione()): (Credentials devono essere impostati.)

def delete_all_items(table_name): 
    # Deletes all items from a DynamoDB table. 
    # You need to confirm your intention by pressing Enter. 
    import boto3 
    client = boto3.client('dynamodb') 
    dynamodb = boto3.resource('dynamodb') 
    table = dynamodb.Table(table_name) 
    response = client.describe_table(TableName=table_name) 
    keys = [k['AttributeName'] for k in response['Table']['KeySchema']] 
    response = table.scan() 
    items = response['Items'] 
    number_of_items = len(items) 
    if number_of_items == 0: # no items to delete 
     print("Table '{}' is empty.".format(table_name)) 
     return 
    print("You are about to delete all ({}) items from table '{}'." 
      .format(number_of_items, table_name)) 
    input("Press Enter to continue...") 
    with table.batch_writer() as batch: 
     for item in items: 
      key_dict = {k: item[k] for k in keys} 
      print("Deleting " + str(item) + "...") 
      batch.delete_item(Key=key_dict) 

delete_all_items("test_table") 

Ovviamente, questo non deve essere utilizzato per le tabelle con un sacco di oggetti . (100+) Per questo, l'approccio di eliminazione/ricreazione è più economico ed efficiente.

4

Come dice Ihtsham, il modo più efficace è eliminare e ricreare la tabella. Tuttavia, se ciò non è pratico (ad esempio a causa della configurazione complessa della tabella, come i trigger Lambda), ecco alcuni comandi AWS CLI per eliminare tutti i record. Richiedono il programma jq per l'elaborazione JSON.

eliminazione di record uno ad uno (! Lento), supponendo che il tavolo si chiama my_table, la vostra chiave di partizione si chiama partition_key, e la vostra chiave di ordinamento (se presente) è chiamato sort_key:

aws dynamodb scan --table-name my_table | \ 
    jq -c '.Items[] | { partition_key, sort_key }' | \ 
    tr '\n' '\0' | \ 
    xargs -0 -n1 -t aws dynamodb delete-item --table-name my_table --key 

Eliminazione record in lotti di fino a 25 record:

aws dynamodb scan --table-name my_table | \ 
    jq -c '[.Items | keys[] as $i | { index: $i, value: .[$i]}] | group_by(.index/25 | floor)[] | { "my_table": [.[].value | { "DeleteRequest": { "Key": { partition_key, sort_key }}}] }' | \ 
    tr '\n' '\0' | \ 
    xargs -0 -n1 -t aws dynamodb batch-write-item --request-items 

Se si inizia a vedere non vuoti UnprocessedItems risposte, la vostra capacità di scrittura è stato superato. Puoi tener conto di ciò riducendo la dimensione del batch. Per me, ogni batch impiega circa un secondo da inviare, quindi con una capacità di scrittura di 5 al secondo, imposto la dimensione del lotto a 5.