Réduction de la taille du fichier de base de données MongoDB

165

J'ai une base de données MongoDB qui était autrefois grande (> 3 Go). Depuis, des documents ont été supprimés et je m'attendais à ce que la taille des fichiers de la base de données diminue en conséquence.

Mais comme MongoDB conserve l'espace alloué, les fichiers sont toujours volumineux.

J'ai lu ici et là que la commande admin mongod --repairest utilisée pour libérer l'espace inutilisé, mais je n'ai pas assez d'espace sur le disque pour exécuter cette commande.

Connaissez-vous un moyen de libérer de l'espace inutilisé?

Meuble
la source
7
Cette question est-elle considérée comme une réponse? Avons-nous besoin de plus de données?
Gates VP
2
à partir de la version 2.8, vous pouvez compresser vos données , ce qui économise beaucoup d'espace.
Salvador Dali
1
J'ai eu exactement le même défi, le moyen le plus simple de le résoudre était de faire une copie de la base de données avec la fonction copyDatabase (), puis de db.dropDatabase () la base de données d'origine, puis de copier la base de données en place. ma base de données était presque vide et quand j'ai fait la copie, seules les données réellement utilisables ont été copiées. la suppression de la base de données d'origine a supprimé les gros fichiers. l'utilisation de db.repairDatabase () n'était pas une option car mon serveur avait déjà peu d'espace disque et cette opération aurait nécessité une très grande quantité d'espace libre, bien plus que nécessaire pour cette opération.
user3892260

Réponses:

144

MISE À JOUR: avec la compactcommande et WiredTiger, il semble que l' espace disque supplémentaire sera effectivement libéré sur le système d'exploitation .


MISE À JOUR: à partir de la v1.9 + il y a une compactcommande.

Cette commande effectuera un compactage "en ligne". Il aura encore besoin d'espace supplémentaire, mais pas autant.


MongoDB compresse les fichiers en:

  • copie des fichiers vers un nouvel emplacement
  • parcourir les documents en boucle et les réorganiser / les resoudre
  • remplacement des fichiers d'origine par les nouveaux fichiers

Vous pouvez faire cette "compression" en exécutant mongod --repairou en vous connectant directement et en exécutant db.repairDatabase().

Dans les deux cas, vous avez besoin de l'espace pour copier les fichiers. Maintenant, je ne sais pas pourquoi vous n'avez pas assez d'espace pour effectuer une compression, cependant, vous avez certaines options si vous avez un autre ordinateur avec plus d'espace.

  1. Exportez la base de données vers un autre ordinateur avec Mongo installé (en utilisant mongoexport), puis vous pouvez importer cette même base de données (en utilisant mongoimport). Cela se traduira par une nouvelle base de données plus compressée. Vous pouvez maintenant arrêter le mongodremplacement d' origine par les nouveaux fichiers de base de données et vous êtes prêt à partir.
  2. Arrêtez le mongod actuel et copiez les fichiers de base de données sur un ordinateur plus grand et exécutez la réparation sur cet ordinateur. Vous pouvez ensuite déplacer les nouveaux fichiers de base de données vers l'ordinateur d'origine.

Il n'y a actuellement pas de bon moyen de "compacter sur place" en utilisant Mongo. Et Mongo peut certainement aspirer beaucoup d'espace.

La meilleure stratégie à l'heure actuelle pour le compactage est d'exécuter une configuration maître-esclave. Vous pouvez ensuite compacter l'esclave, le laisser rattraper et les basculer. Je sais encore un peu poilu. Peut-être que l'équipe Mongo proposera un meilleur compactage en place, mais je ne pense pas que ce soit en haut de leur liste. L'espace disque est actuellement supposé être bon marché (et c'est généralement le cas).

Vice-président Gates
la source
Merci Gates VP pour votre réponse. Je pensais aux deux options que vous avez évoquées. Mais avant de faire de telles choses, je voulais savoir si une solution compacte en place était disponible. Merci encore.
Meuble le
3
À partir d'aujourd'hui (18/11/2010), Dwight (s'exprimant lors de l'événement MongoDC à Washington, DC) a recommandé l'approche répliquer / --repair / basculer si vous souhaitez compacter sans mettre votre base de données hors ligne.
David J.
10
Juste un avertissement 'ne faites pas comme moi' et lancez --repair en tant que root. chowns les fichiers db à la racine. doh.
Totoro
18
La documentation de 'compact' dit: "Cette opération ne réduira pas la quantité d'espace disque utilisée sur le système de fichiers." Je ne comprends pas en quoi c'est une solution à la question initiale.
Ed Norris
Si vous regardez la question d'origine, une partie du problème impliquait d'avoir trop de données pour effectuer une réparation. Si vous avez rempli 2/3 de votre lecteur avec un DB, vous ne pouvez pas effectuer de réparation. Les fichiers nouvellement alloués absorberaient l'espace restant avant que la nouvelle base de données ne soit complètement "copiée et réparée" et "le changement" ne se produirait jamais. Avec compact, il peut au moins garder les fichiers existants en place. Je suis d'accord, ce n'est pas une solution complète, mais c'est une amélioration progressive.
Gates VP
39

J'ai eu le même problème, et je l'ai résolu en faisant simplement ceci en ligne de commande:

mongodump -d databasename
echo 'db.dropDatabase()' | mongo databasename
mongorestore dump/databasename
user435943
la source
assertion: 15936 La création de la collection db.collection a échoué. Errmsg: exception: spécifiez la taille: <n> lorsque plafonné est vrai
tweak2
: On dirait une régression ubuntu ... le fichier de vidage a des métadonnées a plafonné: "non défini" dedans ... la suppression de ces derniers corrige le problème d'importation.
tweak2
2
Ma base de données a noté presque tout le disque. il était de 120 Go (disque 160 Go) Le compact ne réduit pas la taille du fichier et la réparation de la base de données n'est pas possible en raison du manque d'espace. Après mongodump & dropDatabase & mongorestore de db, j'ai 40 Go de taille de base de données.
Igor Benikov
Petite correction à la commande de restaurationmongorestore --db databasename dump/databasename
JERRY
34

Il semble que Mongo v1.9 + prend en charge le compact en place!

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

Consultez la documentation ici: http://docs.mongodb.org/manual/reference/command/compact/

"Contrairement à repairDatabase, la commande compacte ne nécessite pas le double d'espace disque pour faire son travail. Elle nécessite une petite quantité d'espace supplémentaire tout en travaillant. De plus, compact est plus rapide."

awaage
la source
3
@AnujGupta "La commande repairDatabase compacte toutes les collections de la base de données. Elle revient à exécuter la commande compact sur chaque collection individuellement." docs.mongodb.org/manual/reference/command/repairDatabase/… . Donc, si le repairDatabase réduit la taille de manière compacte. J'ai compacté mes collections avec beaucoup de suppression et de mise à jour chaque semaine. J'aime plus compact que repariDatabase car il est d'abord destiné aux collections que vous ne voulez pas à la base de données entière. Deuxièmement, il a juste besoin de 2 Go d'espace libre au lieu de x2 de la taille de votre fichier db (dans mon cas 500 Go).
Maziyar
1
Btw check this out: "MongoDB propose 2 façons différentes de compacter vos données et de restaurer des performances optimales: repairDatabase et compact. RepairDatabase est approprié si vos bases de données sont relativement petites ou si vous pouvez vous permettre de retirer un nœud de la rotation pendant assez longtemps . Pour la taille de nos bases de données et la charge de travail des requêtes, il était plus logique d’exécuter un compactage continu sur toutes nos collections. » 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 - "Contrairement à repairDatabase, compact ne libère pas d'espace sur le système de fichiers".
Anuj Gupta
4
@Maziyar OP veut libérer de l'espace inutilisé , ce qui n'est repairDatabasepas possible compact. compactne libère pas d'espace, il ne fait que défragmenter l'espace utilisé, ce qui ne le réduit pas.
Anuj Gupta
5
A partir de mongo 3.0, compact va récupérer de l' espace si vous utilisez le moteur de stockage WiredTiger.
Gary
19

Compacter toutes les collections dans la base de données actuelle

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

Si vous devez exécuter une réparation complète, utilisez l' repairpathoption. Faites-le pointer vers un disque avec plus d'espace disponible.

Par exemple, sur mon Mac, j'ai utilisé:

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

Mise à jour: selon MongoDB Core Server Ticket 4266 , vous devrez peut-être ajouter --nojournalpour éviter une erreur:

mongod --config /usr/local/etc/mongod.conf --repair --repairpath /Volumes/X/mongo_repair --nojournal
David J.
la source
1
Cela a très bien fonctionné. Je manquais de l'espace 2x requis pour réparer sur place, alors j'ai monté un NAS. Seul problème, il a fallu 18 heures pour terminer, mais cela a fonctionné. Assurez-vous d'ajouter l'indicateur --nojoural.
zenocon
11

À partir de la version 2.8 de Mongo, vous pouvez utiliser la compression . Vous aurez 3 niveaux de compression avec le moteur WiredTiger, mmap (qui est par défaut dans 2.6 ne fournit pas de compression):

Voici un exemple de la quantité d'espace que vous pourrez économiser pour 16 Go de données:

entrez la description de l'image ici

les données sont tirées de cet article.

Salvador Dali
la source
7

Nous devons résoudre 2 façons, basées sur StorageEngine.

1. Moteur MMAP ():

commande: db.repairDatabase ()

REMARQUE: repairDatabase nécessite un espace disque libre égal à la taille de votre ensemble de données actuel plus 2 gigaoctets. Si le volume qui contient dbpath n'a pas suffisamment d'espace, vous pouvez monter un volume séparé et l'utiliser pour la réparation. Lors du montage d'un volume distinct pour repairDatabase, vous devez exécuter repairDatabase à partir de la ligne de commande et utiliser le commutateur --repairpath pour spécifier le dossier dans lequel stocker les fichiers de réparation temporaires. Par exemple: Imaginez que la taille de la base de données soit de 120 Go signifie (120 * 2) +2 = 242 Go d'espace disque requis.

une autre façon de faire la collecte, commande: db.runCommand ({compact: 'collectionName'})

2. WiredTiger: il s'est résolu automatiquement.

Karthickkumar Nagaraj
la source
6

Il y a eu une confusion considérable sur la récupération d'espace dans MongoDB, et certaines pratiques recommandées sont carrément dangereuses à faire dans certains types de déploiement. Plus de détails ci-dessous:

TL; DR repairDatabase tente de récupérer les données d'un déploiement MongoDB autonome qui tente de récupérer après une corruption de disque. S'il récupère de l'espace, c'est purement un effet secondaire . La récupération d'espace ne devrait jamais être la principale considération de l'exécution repairDatabase.

Récupérer de l'espace dans un nœud autonome

WiredTiger: Pour un nœud autonome avec WiredTiger, l'exécution compactlibère de l'espace pour le système d'exploitation, avec une mise en garde: la compactcommande sur WiredTiger sur MongoDB 3.0.x a été affectée par ce bogue: SERVER-21833 qui a été corrigé dans MongoDB 3.2.3. Avant cette version, compactsur WiredTiger pouvait échouer silencieusement.

MMAPv1: en raison du fonctionnement de MMAPv1, il n'existe aucune méthode sûre et prise en charge pour récupérer de l'espace à l'aide du moteur de stockage MMAPv1. compactdans MMAPv1 défragmentera les fichiers de données, rendant potentiellement plus d'espace disponible pour les nouveaux documents, mais cela ne libérera pas d'espace pour le système d'exploitation.

Vous pourrez peut- être exécuter repairDatabasesi vous comprenez parfaitement les conséquences de cette commande potentiellement dangereuse (voir ci-dessous), carrepairDatabase réécrit essentiellement toute la base de données en supprimant les documents corrompus. En tant qu'effet secondaire, cela créera de nouveaux fichiers de données MMAPv1 sans aucune fragmentation et libèrera de l'espace sur le système d'exploitation.

Pour une méthode moins aventureuse, l'exécution mongodumpet mongorestorepeut être également possible dans un déploiement MMAPv1, sous réserve de la taille de votre déploiement.

Récupérer de l'espace dans un jeu de réplicas

Pour les configurations de jeux de réplicas, la méthode la meilleure et la plus sûre pour récupérer de l'espace consiste à effectuer une synchronisation initiale , pour WiredTiger et MMAPv1.

Si vous devez récupérer de l'espace sur tous les nœuds de l'ensemble, vous pouvez effectuer une synchronisation initiale progressive. Autrement dit, effectuez une synchronisation initiale sur chacun des secondaires, avant de finalement abandonner le primaire et d'effectuer une synchronisation initiale sur celui-ci. La méthode de synchronisation initiale continue est la méthode la plus sûre pour effectuer la maintenance du jeu de réplicas, et elle n'implique pas non plus de temps d'arrêt en prime.

Veuillez noter que la faisabilité d'une synchronisation initiale progressive dépend également de la taille de votre déploiement. Pour les déploiements extrêmement volumineux, il peut ne pas être possible d'effectuer une synchronisation initiale et vos options sont donc un peu plus limitées. Si WiredTiger est utilisé, vous pourrez peut- être retirer un secondaire de l'ensemble, le démarrer de manière autonome, l'exécuter compactet le rejoindre dans l'ensemble.

En ce qui concerne repairDatabase

Veuillez ne pas exécuter repairDatabasesur les nœuds du jeu de réplicas . Ceci est très dangereux, comme mentionné dans la page RepairDatabase et décrit plus en détail ci-dessous.

Le nom repairDatabaseest un peu trompeur, car la commande ne tente de rien réparer. La commande était destinée à être utilisée en cas de corruption du disque sur un nœud autonome , ce qui pourrait entraîner la corruption de documents.

La repairDatabasecommande pourrait être plus précisément décrite comme «base de données de récupération». Autrement dit, il recrée les bases de données en supprimant les documents corrompus pour tenter de mettre la base de données dans un état où vous pouvez la démarrer et en récupérer le document intact.

Dans les déploiements MMAPv1, cette reconstruction des fichiers de base de données libère de l'espace pour le système d' exploitation en tant qu'effet secondaire . Libérer de l'espace sur le système d'exploitation n'a jamais été le but.

Conséquences repairDatabasesur un jeu de répliques

Dans un jeu de répliques, MongoDB s'attend à ce que tous les nœuds de l'ensemble contiennent des données identiques. Si vous exécutez repairDatabasesur un nœud de jeu de réplicas, il est possible que le nœud contienne une corruption non détectée et repairDatabasesupprime consciencieusement les documents corrompus pour vous.

De manière prévisible, cela fait que ce nœud contient un ensemble de données différent du reste de l'ensemble. Si une mise à jour atteint ce seul document, l'ensemble peut planter.

Pour aggraver les choses, il est tout à fait possible que cette situation reste en sommeil pendant une longue période, seulement pour frapper soudainement sans raison apparente.

kevinadi
la source
5

Dans le cas où une grande partie de données est supprimée d'une collection et que la collection n'utilise jamais l'espace supprimé pour de nouveaux documents, cet espace doit être renvoyé au système d'exploitation afin qu'il puisse être utilisé par d'autres bases de données ou collections. Vous devrez exécuter une opération de compactage ou de réparation afin de défragmenter l'espace disque et de retrouver l'espace libre utilisable.

Le comportement du processus de compactage dépend du moteur MongoDB comme suit

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

MMAPv1

L'opération de compactage défragmente les fichiers de données et les index. Cependant, il ne libère pas d'espace pour le système d'exploitation. L'opération est toujours utile pour défragmenter et créer un espace plus contigu pour une réutilisation par MongoDB. Cependant, cela ne sert à rien lorsque l'espace disque disponible est très faible.

Un espace disque supplémentaire jusqu'à 2 Go est requis pendant l'opération de compactage.

Un verrou au niveau de la base de données est maintenu pendant l'opération de compactage.

WiredTiger

Le moteur WiredTiger fournit une compression par défaut qui consomme moins d'espace disque que MMAPv1.

Le processus compact libère l'espace libre pour le système d'exploitation. Un espace disque minimal est requis pour exécuter l'opération de compactage. WiredTiger bloque également toutes les opérations sur la base de données car il nécessite un verrouillage au niveau de la base de données.

Pour le moteur MMAPv1 , compact ne renvoie pas l'espace au système d'exploitation. Vous devez exécuter une opération de réparation pour libérer l'espace inutilisé.

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

Mongodb 3.0 et supérieur dispose d'un nouveau moteur de stockage - WiredTiger. Dans mon cas, le moteur de commutation a réduit l'utilisation du disque de 100 Go à 25 Go.

Hett
la source
1

Les fichiers de base de données ne peuvent pas être réduits en taille. Lors de la "réparation" de la base de données, le serveur mongo ne peut supprimer que certains de ses fichiers. Si une grande quantité de données a été supprimée, le serveur mongo "libère" (supprime), pendant la réparation, certains de ses fichiers existants.

Ivankoni
la source
1

En général, compact est préférable à repairDatabase. Mais l'un des avantages de la réparation par rapport au compact est que vous pouvez effectuer une réparation sur l'ensemble du cluster. compact, vous devez vous connecter à chaque partition, ce qui est assez ennuyeux.

user2077221
la source
1

Quand j'ai eu le même problème, j'ai arrêté mon serveur mongo et l'ai redémarré avec la commande

mongod --repair

Avant d'exécuter l'opération de réparation, vous devez vérifier si vous disposez de suffisamment d'espace libre sur votre disque dur (min - est la taille de votre base de données)

Alexandre Makarov
la source
1

Pour le mode autonome, vous pouvez utiliser compact ou réparation,

Pour le cluster partitionné ou le jeu de réplicas, d'après mon expérience, après avoir exécuté compact sur le primaire, puis compacté sur le secondaire, la taille de la base de données primaire a été réduite, mais pas la secondaire. Vous souhaiterez peut- être effectuer une resynchronisation du membre pour réduire la taille de la base de données secondaire. et en faisant cela, vous pourriez constater que la taille de la base de données secondaire est encore plus réduite que la principale, je suppose que la commande compacte ne compacte pas vraiment la collection. Donc, j'ai fini par changer le primaire et le secondaire du jeu de répliques et refaire la resynchronisation du membre .

ma conclusion est que le meilleur moyen de réduire la taille de l'ensemble partitionné / réplique est de resynchroniser le membre, de changer de primaire secondaire et de resynchroniser à nouveau.

wism
la source
0

mongoDB -repair n'est pas recommandé en cas de cluster partitionné.

Si vous utilisez un cluster fragmenté de jeu de réplicas, utilisez la commande compact, elle réécrit et défragmentera toutes les données et les fichiers d'index de toutes les collections. syntaxe:

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

lorsqu'il est utilisé avec force: true, compact s'exécute sur le primaire du jeu de répliques. par exemple db.runCommand ( { command : "collection_name", force : true } )

Autres points à considérer: -Il bloque les opérations. donc recommandé d'exécuter dans la fenêtre de maintenance. -Si les ensembles de réplicas s'exécutant sur des serveurs différents, doivent être exécutés sur chaque membre séparément - En cas de cluster partitionné, le compact doit s'exécuter sur chaque membre de partition séparément. Impossible d'exécuter sur l'instance mongos.

Sève
la source
-5

Juste une façon dont j'ai pu le faire. Aucune garantie sur la sécurité de vos données existantes. Essayez à vos risques et périls.

Supprimez directement les fichiers de données et redémarrez mongod.

Par exemple, avec ubuntu (chemin d'accès par défaut aux données: / var / lib / mongodb), j'avais quelques fichiers avec un nom comme: collection. #. Je garde la collection.0 et j'ai supprimé tous les autres.

Cela semble être un moyen plus simple si vous n'avez pas de données sérieuses dans la base de données.

frnkxiao
la source
les fichiers sont stockés sous <database_name>. <number> par exemple mydb.3 - vous ne pouvez pas dire à la collection.
bobmarksie