amazon web services - pricing - Eliminación de amazon dynamodb
dynamodb vs mongodb (6)
¿Existe alguna forma eficiente de eliminar todos los elementos de una tabla de amazon dynamodb a la vez? He revisado los documentos de aws pero allí se muestra la eliminación de un solo elemento.
Como dice ihtsham, la forma más eficiente es eliminar y volver a crear la tabla. Sin embargo, si eso no es práctico (por ejemplo, debido a la configuración compleja de la tabla, como los activadores de Lambda), aquí hay algunos comandos de AWS CLI para eliminar todos los registros. Requieren el programa jq
para el procesamiento de JSON.
Eliminar registros uno por uno (¡lento!), Asumiendo que su tabla se llama my_table
, que su clave de partición se llama partition_key
, y que su clave de clasificación (si hay alguna) se llama 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
Eliminar registros en lotes de hasta 25 registros:
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
Si comienza a ver respuestas de UnprocessedItems
no están vacías, se ha excedido su capacidad de escritura. Puede dar cuenta de esto reduciendo el tamaño del lote. Para mí, cada lote tarda aproximadamente un segundo en enviarse, por lo que con una capacidad de escritura de 5 por segundo, establezco el tamaño del lote en 5.
DynamoDBMapper hará el trabajo en pocas líneas:
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);
}
Haz los siguientes pasos:
- Hacer solicitud de borrado de tabla
- En la respuesta obtendrás la TableDescription.
- Usando TableDescription cree la tabla otra vez.
Para los pasos 1 y 2 haga clic aquí.
Eso es lo que hago en mi aplicación.
Puede volver a crear una tabla de DynamoDB utilizando AWS Java SDK
// Init DynamoDB client
AmazonDynamoDB dynamoDB = AmazonDynamoDBClientBuilder.standard().build();
// Get table definition
TableDescription tableDescription = dynamoDB.describeTable("my-table").getTable();
// Delete table
dynamoDB.deleteTable("my-table");
// Create table
CreateTableRequest createTableRequest = new CreateTableRequest()
.withTableName(tableDescription.getTableName())
.withAttributeDefinitions(tableDescription.getAttributeDefinitions())
.withProvisionedThroughput(new ProvisionedThroughput()
.withReadCapacityUnits(tableDescription.getProvisionedThroughput().getReadCapacityUnits())
.withWriteCapacityUnits(tableDescription.getProvisionedThroughput().getWriteCapacityUnits())
)
.withKeySchema(tableDescription.getKeySchema());
dynamoDB.createTable(createTableRequest);
Solo para el registro, una solución rápida con eliminación elemento por elemento en Python 3 (utilizando Boto3 y scan () ): (Es necesario configurar las Credentials ).
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")
Obviamente, esto no debe usarse para tablas con muchos elementos . (100+) Para eso, el enfoque de eliminar / recrear es más barato y más eficiente.
BatchWriteItem usar BatchWriteItem si no puede quitar la tabla. Si todas sus entradas están dentro de una sola HashKey, puede usar la API de consulta para recuperar los registros y luego eliminarlos 25 elementos a la vez. Si no, probablemente tendrás que escanear.
Alternativamente, puede proporcionar un envoltorio simple alrededor de AmazonDynamoDBClient
(del SDK oficial) que recopila un conjunto de claves Hash / Range que existen en su tabla. Entonces no necesitaría consultar o buscar los elementos que insertó después de la prueba, ya que ya tendría el Conjunto construido. Eso se vería algo así:
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
es una clase dentro del SDK de DynamoDB que acepta cero, uno o dos objetos AttributeValue
en el constructor para representar una clave hash o una clave hash / range. Suponiendo que los métodos hashCode
y hashCode
funcionen, puede utilizarlos dentro del Set
que describí. Si no lo hacen, tendrás que escribir tu propia clase Key
.
Esto debería proporcionarle un conjunto mantenido para usar dentro de sus pruebas. No es específico de una tabla, por lo que es posible que deba agregar otra capa de colección si está usando varias tablas. Eso cambiaría Set<Key>
a algo como Map<TableName, Set<Key>>
. Necesitaría mirar la propiedad getTableName()
para elegir el Set
correcto para actualizar.
Una vez que finalice la prueba, agarrar el contenido de la tabla y eliminarla debería ser sencillo.
Una sugerencia final: use una tabla diferente para la prueba que la que usa para su aplicación. Cree un esquema idéntico, pero asigne un nombre diferente a la tabla. Es probable que incluso desee que un usuario de IAM diferente evite que su código de prueba acceda a su tabla de producción. Si tiene preguntas sobre eso, siéntase libre de abrir una pregunta separada para ese escenario.