¿Cuál es la forma recomendada de eliminar una gran cantidad de elementos de DynamoDB?


111

Estoy escribiendo un servicio de registro simple en DynamoDB.

Tengo una tabla de registros que está codificada por un hash user_id y un rango de marca de tiempo (Unix epoch int).

Cuando un usuario del servicio cancela su cuenta, necesito eliminar todos los elementos de la tabla, independientemente del valor del rango.

¿Cuál es la forma recomendada de realizar este tipo de operación (teniendo en cuenta que podría haber millones de elementos para eliminar)?

Mis opciones, por lo que puedo ver, son:

R: Realice una operación de escaneo, llamando a eliminar en cada artículo devuelto, hasta que no quede ningún artículo

B: Realice una operación BatchGet, nuevamente llamando a eliminar en cada elemento hasta que no quede ninguno

Ambos me parecen terribles, ya que tomarán mucho tiempo.

Lo que idealmente quiero hacer es llamar a LogTable.DeleteItem (user_id) - Sin proporcionar el rango, y hacer que elimine todo por mí.

Respuestas:


52

Lo que idealmente quiero hacer es llamar a LogTable.DeleteItem (user_id) - Sin proporcionar el rango, y hacer que elimine todo por mí.

Ciertamente una solicitud comprensible; Me imagino que el equipo de AWS podría agregar operaciones avanzadas como estas con el tiempo (tienen un historial de comenzar con un conjunto de funciones limitado primero y evaluar las extensiones según los comentarios de los clientes), pero esto es lo que debe hacer para evitar el costo de un escaneo completo al menos:

  1. Use Query en lugar de Scan para recuperar todos los elementos para user_id: esto funciona independientemente de la clave primaria combinada de hash / rango en uso, porque HashKeyValue y RangeKeyCondition son parámetros separados en esta API y el primero solo apunta al valor de atributo del componente hash del compuesto Clave primaria. .

    • Tenga en cuenta que tendrá que lidiar con la paginación de la API de consulta aquí como de costumbre, consulte el parámetro ExclusiveStartKey :

      Clave principal del elemento desde el que continuar una consulta anterior. Una consulta anterior podría proporcionar este valor como LastEvaluateKey si esa operación de consulta se interrumpió antes de completar la consulta; ya sea por el tamaño del conjunto de resultados o por el parámetro Límite. LastEvaluateKey puede devolverse en una nueva solicitud de consulta para continuar la operación desde ese punto.

  2. Recorra todos los artículos devueltos y facilite DeleteItem como de costumbre

    • Actualización : lo más probable es que BatchWriteItem sea ​​más apropiado para un caso de uso como este (consulte los detalles a continuación).

Actualizar

Como destacó ivant , la operación BatchWriteItem le permite colocar o eliminar varios elementos en varias tablas en una sola llamada a la API [énfasis mío] :

Para cargar un elemento, puede usar la API PutItem y para eliminar un elemento, puede usar la API DeleteItem. Sin embargo, cuando desee cargar o eliminar grandes cantidades de datos, como cargar grandes cantidades de datos de Amazon Elastic MapReduce (EMR) o migrar datos de otra base de datos a Amazon DynamoDB, esta API ofrece una alternativa eficiente.

Tenga en cuenta que esto todavía tiene algunas limitaciones relevantes, en particular:

  • Máximo de operaciones en una sola solicitud : puede especificar un total de hasta 25 operaciones de colocación o eliminación; sin embargo, el tamaño total de la solicitud no puede exceder 1 MB (la carga útil HTTP).

  • No es una operación atómica: las operaciones individuales especificadas en un BatchWriteItem son atómicas; sin embargo, BatchWriteItem en su conjunto es una operación de "mejor esfuerzo" y no una operación atómica. Es decir, en una solicitud BatchWriteItem, algunas operaciones pueden tener éxito y otras pueden fallar. [...]

Sin embargo, esto obviamente ofrece una ganancia potencialmente significativa para casos de uso como el que nos ocupa.


4
Creo que tendría sentido utilizar la eliminación por lotes para el segundo paso (está "enmascarado" como una operación de escritura por lotes )
ivant

1
@ivant - muchas gracias por la sugerencia, esta funcionalidad de eliminación "enmascarada" de BatchWriteItem se me escapó entonces; Actualicé la respuesta en consecuencia.
Steffen Opel

para eliminar con BatchWriteItemelementos debe especificarse a través deTableWriteItems
Neil

1
Tony

3
Me doy cuenta de que esto es antiguo, y el OP no mencionó un SDK de lenguaje específico, pero en Python hay un alto nivel batch_writer()como parte de la boto3.resource.TableAPI que "manejará automáticamente el almacenamiento en búfer y el envío de elementos en lotes. Además, el escritor de lotes también maneja automáticamente cualquier elemento no procesado y reenvíalo según sea necesario "es decir, es un envoltorio alrededor de BatchWriteItem que administra las partes molestas. boto3.amazonaws.com/v1/documentation/api/latest/reference/…
Davos

46

Según la documentación de DynamoDB, puede eliminar la tabla completa.

Vea abajo:

"Eliminar una tabla completa es significativamente más eficiente que eliminar elementos uno por uno, lo que básicamente duplica el rendimiento de escritura, ya que realiza tantas operaciones de eliminación como operaciones de colocación"

Si desea eliminar solo un subconjunto de sus datos, puede crear tablas separadas para cada mes, año o similar. De esta manera, podría eliminar "el mes pasado" y mantener intactos el resto de sus datos.

Así es como se elimina una tabla en Java con el AWS SDK:

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

8
También me gusta esta respuesta, pero cuidado: esto podría crear muchas tablas en su sistema y pagamos por provisión de mesa. Por lo tanto, debe reducir el aprovisionamiento después de fin de mes (si su tabla es por mes) mientras esta tabla no se elimine.
Sergio MC Figueiredo

2
de acuerdo con esta respuesta, se aplica si necesita eliminar todos los registros de la tabla, pero aquí el interrogador desea eliminar las entradas de la base de usuarios, no toda la tabla.
Ihtsham Minhas

1
Tener una tabla separada para cada usuario sería costoso dado el precio de DynamoDB. Una mesa al mes empeoraría las cosas. Esta es claramente una respuesta para un problema diferente y muy específico.
André Werlang

11
Eliminar la tabla también puede no ser una opción atractiva si utiliza el aprovisionamiento automatizado como CloudFormation para administrar su tabla como parte de una pila. No conozco una forma sencilla de hacer que CloudFormation vuelva a crear una tabla que eliminó a mano.
brabster

2
Este enfoque lleva bastante tiempo eliminar y volver a crear (cuando sea necesario) la tabla, por lo que no está disponible durante todo el tiempo. La pregunta establece claramente la eliminación de los datos del usuario, lo que sería poco práctico dividir en tablas separadas por usuario.
André Werlang

13

Si desea eliminar elementos después de un tiempo, por ejemplo, después de un mes, simplemente use la opción Tiempo de vida. Será no contar con unidades de escritura.

En su caso, agregaría ttl cuando vencen los registros y los dejaría después de que se elimine un usuario. TTL se aseguraría de que los registros se eliminen eventualmente.

Cuando Time To Live está habilitado en una mesa, un trabajo en segundo plano verifica el atributo TTL de los elementos para ver si están vencidos.

DynamoDB generalmente elimina los elementos caducados dentro de las 48 horas posteriores a la caducidad. La duración exacta dentro de la cual un elemento se elimina realmente después de su vencimiento es específica de la naturaleza de la carga de trabajo y el tamaño de la tabla. Los elementos que han expirado y no se han eliminado seguirán apareciendo en lecturas, consultas y escaneos. Estos elementos aún se pueden actualizar y se respetarán las actualizaciones exitosas para cambiar o eliminar el atributo de vencimiento.

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


agregar TTL es una "actualización" (operación de escritura). No estoy seguro de que haya alguna ganancia por hacer una "actualización" en lugar de una "eliminación".
Tomer

puede tener esos datos insertados con escritura original y actualizados con cualquier otra acción de actualización. Por supuesto, no es una opción si tiene una gran cantidad de datos y luego desea eliminarlos. Pero esta es una opción válida para los casos en los que puede tener ttl para los datos que inserta o actualiza.
Lukas Liesis

1
Estoy de acuerdo, si ya hay TTL configurado y la limpieza puede esperar hasta 48 horas, esa es definitivamente la opción óptima. Mis disculpas si no estaba claro.
Tomer

4

La respuesta a esta pregunta depende de la cantidad de artículos, su tamaño y su presupuesto. Depende de que tengamos los siguientes 3 casos:

1- El número de elementos y el tamaño de los elementos de la tabla no son muchos. luego, como dijo Steffen Opel, puede usar Query en lugar de Scan para recuperar todos los elementos para user_id y luego recorrer todos los elementos devueltos y facilitar DeleteItemoBatchWriteItem. Pero tenga en cuenta que puede quemar mucha capacidad de rendimiento aquí. Por ejemplo, considere una situación en la que necesita eliminar 1000 elementos de una tabla de DynamoDB. Suponga que cada elemento tiene un tamaño de 1 KB, lo que da como resultado alrededor de 1 MB de datos. Esta tarea de eliminación masiva requerirá un total de 2000 unidades de capacidad de escritura para realizar consultas y eliminar. Para realizar esta carga de datos en 10 segundos (que ni siquiera se considera tan rápido en algunas aplicaciones), necesitaría establecer el rendimiento de escritura aprovisionado de la tabla en 200 unidades de capacidad de escritura. Como puede ver, es factible usarlo de esta manera si es para una menor cantidad de artículos o artículos de tamaño pequeño.

2- Tenemos muchos artículos o artículos muy grandes en la mesa y podemos almacenarlos según el tiempo en diferentes mesas. Entonces, como dijo Jonathan, puede eliminar la tabla. esto es mucho mejor, pero no creo que coincida con su caso. Como desea eliminar todos los datos de los usuarios sin importar la hora de creación de los registros, en este caso no puede eliminar una tabla en particular. Si desea tener una tabla separada para cada usuario, supongo que si el número de usuarios es alto, entonces es muy caro y no es práctico para su caso.

3- Si tiene una gran cantidad de datos y no puede dividir sus datos calientes y fríos en diferentes tablas y necesita hacer una eliminación a gran escala con frecuencia, lamentablemente DynamoDB no es una buena opción para usted. Puede resultar más caro o muy lento (depende de su presupuesto). En estos casos recomiendo buscar otra base de datos para sus datos.


0

Mi enfoque para eliminar todas las filas de una tabla en DynamoDb es simplemente extraer todas las filas de la tabla, usar DynamoDbs ScanAsync y luego enviar la lista de resultados a DynamoDbs AddDeleteItems. El siguiente código en C # funciona bien para mí.

        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: Eliminar la tabla y luego volver a crearla desde la consola web puede causar problemas si usa YAML / CloudFront para crear la tabla.


0

No tenemos la opción de truncar las tablas de dinamo. tenemos que soltar la mesa y volver a crear. Los cargos de DynamoDB se basan en ReadCapacityUnits y WriteCapacityUnits. Si eliminamos todos los elementos usando la función BatchWriteItem, usará WriteCapacityUnits. Así que es mejor eliminar registros específicos o eliminar la tabla y comenzar de nuevo.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.