Reducir el tamaño del archivo de base de datos MongoDB

165

Tengo una base de datos MongoDB que alguna vez fue grande (> 3GB). Desde entonces, los documentos se han eliminado y esperaba que el tamaño de los archivos de la base de datos disminuyera en consecuencia.

Pero como MongoDB mantiene el espacio asignado, los archivos siguen siendo grandes.

Leí aquí y allá que el comando admin mongod --repairse usa para liberar el espacio no utilizado, pero no tengo suficiente espacio en el disco para ejecutar este comando.

¿Conoces alguna forma de liberar espacio no utilizado?

Meuble
fuente
77
¿Esta pregunta se considera respondida? ¿Necesitamos más datos?
Gates VP
2
a partir de la versión 2.8, puede comprimir sus datos , lo que ahorra una cantidad significativa de espacio.
Salvador Dali
1
Tuve el mismo desafío exacto, la forma más fácil de resolverlo fue hacer una copia de la base de datos con la función copyDatabase (), luego db.dropDatabase () la base de datos original y luego volver a copiar la base de datos en su lugar. mi base de datos estaba mayormente vacía y cuando hice la copia, solo se copiaron los datos utilizables reales. soltar la base de datos original eliminó los archivos grandes. El uso de db.repairDatabase () no era una opción ya que mi servidor ya tenía poco espacio en disco y esta operación habría requerido una gran cantidad de espacio libre, mucho más de lo necesario para esta operación.
user3892260

Respuestas:

144

ACTUALIZACIÓN: con el compactcomando y WiredTiger parece que el espacio en disco adicional se liberará al sistema operativo .


ACTUALIZACIÓN: a partir de v1.9 + hay un compactcomando.

Este comando realizará una compactación "en línea". Todavía necesitará algo de espacio extra, pero no tanto.


MongoDB comprime los archivos de la siguiente manera:

  • copiando los archivos a una nueva ubicación
  • recorrer los documentos y reordenarlos / resolverlos nuevamente
  • reemplazando los archivos originales con los nuevos archivos

Puede hacer esta "compresión" ejecutando mongod --repairo conectándose directamente y ejecutando db.repairDatabase().

En cualquier caso, necesita espacio para copiar los archivos. Ahora no sé por qué no tiene suficiente espacio para realizar una compresión, sin embargo, tiene algunas opciones si tiene otra computadora con más espacio.

  1. Exporte la base de datos a otra computadora con Mongo instalado (usando mongoexport) y luego puede importar esa misma base de datos (usando mongoimport). Esto dará como resultado una nueva base de datos que está más comprimida. Ahora puede detener el mongodreemplazo original con los nuevos archivos de la base de datos y listo.
  2. Detenga el mongod actual y copie los archivos de la base de datos a una computadora más grande y ejecute la reparación en esa computadora. Luego, puede mover los nuevos archivos de la base de datos a la computadora original.

Actualmente no hay una buena manera de "compactar en el lugar" con Mongo. Y Mongo definitivamente puede absorber mucho espacio.

La mejor estrategia en este momento para la compactación es ejecutar una configuración Master-Slave. Luego puede compactar el Esclavo, dejar que se ponga al día y cambiarlo. Todavía sé un poco peludo. Tal vez el equipo de Mongo tenga una mejor compactación in situ, pero no creo que sea una prioridad en su lista. Actualmente se supone que el espacio en disco es barato (y generalmente lo es).

Vicepresidente de Gates
fuente
Gracias vicepresidente de Gates por su respuesta. Estaba pensando en las dos opciones que mencionaste. Pero antes de hacer esas cosas, quería saber si había una solución compacta disponible. Gracias de nuevo.
Meuble
3
A partir de hoy (2010-11-18) Dwight (hablando en el evento MongoDC en Washington, DC) recomendó el enfoque de replicación / reparación / cambio si desea compactar sin desconectar su base de datos.
David J.
10
Solo un aviso "no hagas lo que hice" y ejecuta --repair como root. baja los archivos db a la raíz. doh
Totoro
18
La documentación de 'compact' dice: "Esta operación no reducirá la cantidad de espacio en disco utilizado en el sistema de archivos". No entiendo cómo esta es una solución a la pregunta original.
Ed Norris
Si observa la pregunta original, parte del problema implicaba tener demasiados datos para realizar una reparación. Si ha llenado 2/3 de su unidad con un DB, no podría realizar una reparación. Los archivos recién asignados absorberían el espacio restante antes de que el nuevo DB fuera completamente "copiado y reparado" y "el cambio" nunca sucedería. Con compactél, al menos puede mantener los archivos existentes en su lugar. Estoy de acuerdo, no es una solución completa, pero es una mejora incremental.
Gates VP
39

Tuve el mismo problema y lo resolví simplemente haciendo esto en la línea de comando:

mongodump -d databasename
echo 'db.dropDatabase()' | mongo databasename
mongorestore dump/databasename
usuario435943
fuente
aserción: 15936 Error al crear la colección db.collection. Errmsg: excepción: especificar tamaño: <n> cuando el límite es verdadero
tweak2
: Parece una regresión de ubuntu ... el archivo de volcado tiene metadatos con un límite: "indefinido" en él ... al eliminar estas soluciones, el problema de importación.
tweak2
2
Mi base de datos ha calificado casi todo el disco. tenía 120 GB (disco de 160 GB) El compacto no reduce el tamaño del archivo y la reparación La base de datos no es posible debido a la falta de espacio. Después de mongodump & dropDatabase & mongorestore de db tengo 40 GB de tamaño de base de datos.
Igor Benikov
Pequeña corrección al comando de restauraciónmongorestore --db databasename dump/databasename
JERRY
34

¡Parece que Mongo v1.9 + tiene soporte para el compacto en su lugar!

> db.runCommand( { compact : 'mycollectionname' } )

Vea los documentos aquí: http://docs.mongodb.org/manual/reference/command/compact/

"A diferencia de RepairDatabase, el comando compacto no requiere doble espacio en disco para hacer su trabajo. Requiere una pequeña cantidad de espacio adicional mientras trabaja. Además, compacto es más rápido".

esperar
fuente
3
@AnujGupta "El comando repairDatabase compacta todas las colecciones de la base de datos. Es idéntico a ejecutar el comando compacto en cada colección individualmente". docs.mongodb.org/manual/reference/command/repairDatabase/… . Entonces, si RepairDatabase reduce el tamaño tan compacto. He estado compactando mis colecciones con muchas eliminaciones y actualizaciones cada semana. Me gusta más el compacto que repariDatabase porque primero está dirigido a colecciones que no desea toda la base de datos. En segundo lugar, solo necesita 2GB de espacio libre en lugar de x2 de su tamaño de archivo db (en mi caso 500GB).
Maziyar
1
Por cierto, compruebe esto: "MongoDB proporciona 2 formas diferentes de compactar sus datos y restaurar el rendimiento óptimo: RepairDatabase y compact. RepairDatabase es apropiado si sus bases de datos son relativamente pequeñas, o puede permitirse sacar un nodo de la rotación durante bastante tiempo . Para los tamaños de nuestra base de datos y la carga de trabajo de consultas, tenía más sentido ejecutar una compactación continua en todas nuestras colecciones ". blog.parse.com/2013/03/26/always-be-compacting github.com/ParsePlatform/Ops/blob/master/tools/mongo_compact.rb
Maziyar
3
@Maziyar docs.mongodb.org/manual/reference/command/compact/#disk-space - "A diferencia de repairDatabase, compact no libera espacio en el sistema de archivos".
Anuj Gupta
44
@Maziyar OP quiere liberar espacio no utilizado , lo que se logra a través de repairDatabase, no compact. compactno libera espacio, solo desfragmenta el espacio usado, lo que no lo reduce.
Anuj Gupta
55
A partir de mongo 3.0, compact será recuperar espacio si se utiliza el motor de almacenamiento WiredTiger.
Gary
19

Compactar todas las colecciones en la base de datos actual

db.getCollectionNames().forEach(function (collectionName) {
    print('Compacting: ' + collectionName);
    db.runCommand({ compact: collectionName });
});
OzzyCzech
fuente
13

Si necesita ejecutar una reparación completa, use la repairpathopción. Apúntelo a un disco con más espacio disponible.

Por ejemplo, en mi Mac he usado:

mongod --config /usr/local/etc/mongod.conf --repair --repairpath /Volumes/X/mongo_repair

Actualización: según el ticket 4266 del servidor central de MongoDB , es posible que deba agregar --nojournalpara evitar un error:

mongod --config /usr/local/etc/mongod.conf --repair --repairpath /Volumes/X/mongo_repair --nojournal
David J.
fuente
1
Esto funcionó muy bien. Me faltaba el doble de espacio requerido para reparar en su lugar, así que monté un NAS. El único problema fue que tardó 18 horas en completarse, pero funcionó. Asegúrese de agregar la bandera --nojoural.
zenocon
11

A partir de la versión 2.8 de Mongo, puede usar la compresión . Tendrá 3 niveles de compresión con el motor WiredTiger, mmap (que por defecto en 2.6 no proporciona compresión):

Aquí hay un ejemplo de cuánto espacio podrá ahorrar para 16 GB de datos:

ingrese la descripción de la imagen aquí

Los datos se toman de este artículo.

Salvador Dalí
fuente
7

Necesitamos resolver 2 formas, basadas en StorageEngine.

1. Motor MMAP ():

comando: db.repairDatabase ()

NOTA: RepairDatabase requiere espacio libre en disco igual al tamaño de su conjunto de datos actual más 2 gigabytes. Si el volumen que contiene dbpath no tiene suficiente espacio, puede montar un volumen separado y usarlo para la reparación. Al montar un volumen separado para repairDatabase, debe ejecutar repairDatabase desde la línea de comandos y usar el modificador --repairpath para especificar la carpeta en la que almacenar los archivos de reparación temporales. por ejemplo: el tamaño de Imagine DB es de 120 GB, significa (120 * 2) +2 = se requiere 242 GB de espacio en el disco duro.

otra forma de recopilación inteligente, comando: db.runCommand ({compact: 'collectionName'})

2. WiredTiger: se resuelve automáticamente.

Karthickkumar Nagaraj
fuente
6

Ha habido una considerable confusión sobre la recuperación de espacio en MongoDB, y algunas prácticas recomendadas son francamente peligrosas en ciertos tipos de implementación. Más detalles a continuación:

TL; DR repairDatabase intenta recuperar datos de una implementación independiente de MongoDB que está intentando recuperarse de un daño en el disco. Si recupera espacio, es puramente un efecto secundario . La recuperación del espacio nunca debería ser la consideración principal de la ejecución repairDatabase.

Recuperar espacio en un nodo independiente

WiredTiger: para un nodo independiente con WiredTiger, la ejecución compactliberará espacio para el sistema operativo, con una advertencia: el compactcomando en WiredTiger en MongoDB 3.0.x se vio afectado por este error: SERVER-21833 que se corrigió en MongoDB 3.2.3. Antes de esta versión, compacten WiredTiger podía fallar silenciosamente.

MMAPv1: debido a la forma en que funciona MMAPv1, no existe un método seguro y compatible para recuperar espacio utilizando el motor de almacenamiento MMAPv1. compacten MMAPv1 desfragmentará los archivos de datos, potencialmente haciendo más espacio disponible para nuevos documentos, pero no liberará espacio de nuevo al sistema operativo.

Es posible que pueda ejecutar repairDatabasesi comprende completamente las consecuencias de este comando potencialmente peligroso (ver más abajo), ya que repairDatabaseesencialmente reescribe toda la base de datos descartando documentos corruptos. Como efecto secundario, esto creará nuevos archivos de datos MMAPv1 sin ninguna fragmentación y liberará espacio al sistema operativo.

Para un método menos aventurero, ejecutar mongodumpy también mongorestorepuede ser posible en una implementación MMAPv1, sujeto al tamaño de su implementación.

Recuperar espacio en un conjunto de réplicas

Para configuraciones de conjunto de réplica, el mejor y más seguro método para recuperar espacio es realizar una sincronización inicial , tanto para WiredTiger como para MMAPv1.

Si necesita recuperar espacio de todos los nodos del conjunto, puede realizar una sincronización inicial continua. Es decir, realice la sincronización inicial en cada una de las secundarias, antes de finalmente bajar la primaria y realizar la sincronización inicial en ella. El método de sincronización inicial progresiva es el método más seguro para realizar el mantenimiento del conjunto de réplicas, y tampoco implica un tiempo de inactividad como beneficio adicional.

Tenga en cuenta que la viabilidad de realizar una sincronización inicial continua también depende del tamaño de su implementación. Para implementaciones extremadamente grandes, puede que no sea factible hacer una sincronización inicial y, por lo tanto, sus opciones son algo más limitadas. Si se usa WiredTiger, es posible que pueda quitar un secundario del conjunto, iniciarlo de forma independiente, ejecutarlo compacty volver a unirlo al conjunto.

Respecto a repairDatabase

No ejecute repairDatabaseen nodos de conjunto de réplica . Esto es muy peligroso, como se menciona en la página RepairDatabase y se describe con más detalles a continuación.

El nombre repairDatabasees un poco engañoso, ya que el comando no intenta reparar nada. El comando estaba destinado a utilizarse cuando hay daños en el disco en un nodo independiente , lo que podría conducir a documentos corruptos.

El repairDatabasecomando podría describirse con mayor precisión como "base de datos de recuperación". Es decir, recrea las bases de datos descartando documentos corruptos en un intento de llevar la base de datos a un estado en el que pueda iniciarla y recuperar el documento intacto.

En las implementaciones de MMAPv1, esta reconstrucción de los archivos de la base de datos libera espacio al sistema operativo como efecto secundario . Liberar espacio para el sistema operativo nunca fue el propósito.

Consecuencias de repairDatabaseen un conjunto de réplicas

En un conjunto de réplica, MongoDB espera que todos los nodos del conjunto contengan datos idénticos. Si se ejecuta repairDatabaseen un nodo de conjunto de réplicas, existe la posibilidad de que el nodo contenga corrupción no detectada y repairDatabaseelimine debidamente los documentos corruptos por usted.

Como era de esperar, esto hace que ese nodo contenga un conjunto de datos diferente del resto del conjunto. Si una actualización llega a ese único documento, todo el conjunto podría fallar.

Para empeorar las cosas, es completamente posible que esta situación permanezca latente durante mucho tiempo, solo para golpear repentinamente sin razón aparente.

kevinadi
fuente
5

En caso de que una gran cantidad de datos se elimine de una colección y la colección nunca use el espacio eliminado para nuevos documentos, este espacio debe devolverse al sistema operativo para que otras bases de datos o colecciones puedan usarlo. Deberá ejecutar una operación compacta o de reparación para desfragmentar el espacio en disco y recuperar el espacio libre utilizable.

El comportamiento del proceso de compactación depende del motor MongoDB de la siguiente manera

db.runCommand({compact: collection-name })

MMAPv1

La operación de compactación desfragmenta archivos de datos e índices. Sin embargo, no libera espacio para el sistema operativo. La operación sigue siendo útil para desfragmentar y crear más espacio contiguo para su reutilización por MongoDB. Sin embargo, no sirve de nada cuando el espacio libre en disco es muy bajo.

Se requiere un espacio de disco adicional de hasta 2 GB durante la operación de compactación.

Se mantiene un bloqueo de nivel de base de datos durante la operación de compactación.

WiredTiger

El motor WiredTiger proporciona compresión por defecto que consume menos espacio en disco que MMAPv1.

El proceso compacto libera el espacio libre para el sistema operativo. Se requiere un espacio mínimo en disco para ejecutar la operación compacta. WiredTiger también bloquea todas las operaciones en la base de datos, ya que necesita bloqueo de nivel de base de datos.

Para el motor MMAPv1 , compacto no devuelve el espacio al sistema operativo. Debe ejecutar la operación de reparación para liberar el espacio no utilizado.

db.runCommand({repairDatabase: 1})
VISHAL KUMAWAT
fuente
3

Mongodb 3.0 y superior tiene un nuevo motor de almacenamiento: WiredTiger. En mi caso, el cambio de motor redujo el uso del disco de 100 Gb a 25 Gb.

Hett
fuente
1

Los archivos de base de datos no pueden reducirse de tamaño. Mientras se "repara" la base de datos, solo es posible que el servidor mongo elimine algunos de sus archivos. Si se ha eliminado una gran cantidad de datos, el servidor mongo "liberará" (eliminará), durante la reparación, algunos de sus archivos existentes.

ivankoni
fuente
1

En general, compacto es preferible a repararDatabase. Pero una ventaja de la reparación en comparación es que puede realizar reparaciones en todo el clúster. compact tienes que iniciar sesión en cada fragmento, lo cual es un poco molesto.

usuario2077221
fuente
1

Cuando tuve el mismo problema, detuve mi servidor mongo y lo volví a iniciar con el comando

mongod --repair

Antes de ejecutar la operación de reparación, debe verificar si tiene suficiente espacio libre en su HDD (min - es el tamaño de su base de datos)

Alexander Makarov
fuente
1

Para el modo independiente, puede usar compacto o reparar,

Para el clúster fragmentado o el conjunto de réplica, en mi experiencia, después de ejecutar compact en el primario, seguido de compact el secundario, el tamaño de la base de datos primaria se redujo, pero no el secundario. Es posible que desee volver a sincronizar el miembro para reducir el tamaño de la base de datos secundaria. y al hacer esto, puede encontrar que el tamaño de la base de datos secundaria se reduce aún más que el primario, supongo que el comando compacto realmente no compacta la colección. Entonces, terminé cambiando el primario y el secundario del conjunto de réplicas y volviendo a sincronizar el miembro .

mi conclusión es que la mejor manera de reducir el tamaño del conjunto fragmentado / réplica es haciendo que el miembro de resincronización, cambie el primario secundario y vuelva a sincronizar.

wism
fuente
0

mongoDB -repair no se recomienda en caso de agrupación fragmentada.

Si usa el clúster fragmentado de conjunto de réplicas, use el comando compacto, reescribirá y desfragmentará todos los archivos de datos e índices de todas las colecciones. sintaxis:

db.runCommand( { compact : "collection_name" } )

cuando se usa con fuerza: verdadero, compacto se ejecuta en primario del conjunto de réplica. p.ej db.runCommand ( { command : "collection_name", force : true } )

Otros puntos a considerar: - Bloquea las operaciones. tan recomendado para ejecutar en la ventana de mantenimiento. -Si los conjuntos de réplicas se ejecutan en diferentes servidores, deben ejecutarse en cada miembro por separado: en el caso de un clúster fragmentado, compact debe ejecutarse en cada miembro fragmentado por separado. No se puede ejecutar contra la instancia de mongos.

Savia
fuente
-5

Solo una forma en que pude hacerlo. No hay garantía sobre la seguridad de sus datos existentes. Intenta con tu propio riesgo.

Elimine los archivos de datos directamente y reinicie mongod.

Por ejemplo, con ubuntu (ruta predeterminada a los datos: / var / lib / mongodb), tuve un par de archivos con un nombre como: colección. #. Mantengo la colección.0 y eliminé todos los demás.

Parece una manera más fácil si no tiene datos serios en la base de datos.

frnkxiao
fuente
los archivos se almacenan como <database_name>. <número> por ejemplo, mydb.3: no puede decirle a la colección.
bobmarksie