MongoDB muy lento al eliminar muchos y remover
En mi base de datos de MongoDB con 2 réplicas tengo una colección con más de 100 millones de documentos, el tamaño de la colección es de más de 400 GB y el tamaño de los índices es de 150 GB. Tengo que reducir el tamaño de la colección eliminando los registros más antiguos utilizando el campo modifiedOn
para el cual tengo un índice de TTL. El índice de TTL eliminará las entradas anteriores a un mes, pero tengo que actuar ahora. He intentado eliminar los registros más antiguos utilizando:
db.myCollection.deleteMany({modifiedOn : {"$lt" : new Date(2021, 12, 20}})
y
db.myCollection.remove({modifiedOn : {"$lt" : new Date(2021, 12, 20}})
Estaba intentando aumentar el día y luego ejecutar la consulta para reducir la carga, pero lleva al menos 10 horas completar estas consultas. Sé que eliminar la colección es la opción más rápida, pero quiero conservar los datos más recientes.
¿Por qué exactamente tarda tanto tiempo en ejecutar estas consultas incluso con un índice para modifiedOn
? ¿Es el índice demasiado grande y actualizarlo lleva tanto tiempo? ¿Cuáles son las mejores opciones para eliminar los registros más antiguos?
davy.ai
Explicación
La razón por la cual las consultas para eliminar los registros más antiguos tardan tanto en ejecutarse, a pesar de tener un índice para
modifiedOn
, es porque MongoDB necesita escanear toda la colección para encontrar los documentos coincidentes. Esto se debe a que la consulta no es lo suficientemente selectiva y no utiliza ningún otro índice.Además, la eliminación de documentos en MongoDB puede ser una operación lenta debido a la forma en que maneja el espacio en disco. Cuando se elimina un documento, en lugar de liberar inmediatamente el espacio en disco, MongoDB lo marca como eliminado y deja el espacio disponible para futuras escrituras. Esto significa que la eliminación real de los datos del disco puede llevar algún tiempo, especialmente si la colección está muy fragmentada.
Mejores opciones
Para eliminar los registros más antiguos de manera más eficiente, puedes probar una o más de las siguientes opciones:
Eliminación por lotes: En lugar de eliminar todos los documentos de una vez, puedes eliminarlos por lotes de un tamaño determinado, utilizando el método
limit()
. Esto puede ayudar a reducir la carga en la base de datos y hacer que el proceso de eliminación sea más manejable.Usar una consulta de rango: Si estás seguro de que el campo
modifiedOn
siempre aumenta, puedes utilizar una consulta de rango para eliminar todos los documentos que sean anteriores a una determinada fecha. Por ejemplo, puedes utilizar la siguiente consulta para eliminar todos los documentos que sean anteriores al 20 de diciembre de 2021:Esta consulta debería ser más rápida que la consulta original, ya que puede aprovechar el índice en
modifiedOn
.Usar
mongodump
ymongorestore
: Otra opción es utilizar las utilidadesmongodump
ymongorestore
para crear una copia de seguridad de los datos más recientes y luego restaurarla en una nueva colección. De esta manera, puedes descartar los datos antiguos y comenzar con una colección nueva que solo contenga los datos más recientes. Sin embargo, esta opción puede no ser práctica si el tamaño de los datos es demasiado grande.