15

I want to shrink data files size by reclaiming deleted space, but I can't run db.repairDatabase(), because free disk space is not enough.

user805627
  • 4,247
  • 6
  • 32
  • 43
  • Can you move your files to another disk/machine and do this? I think this is one of the pain points in the existing mongo toolset: What to do when you run out of disk space. – Eve Freeman Jul 23 '12 at 18:20

5 Answers5

16

Update: With WiredTiger, compact does free space.

The original answer to this question is here: Reducing MongoDB database file size

There really is nothing outside of repair that will reclaim space. The compact should allow you to go much longer on the existing space. Otherwise, you will have to migrate to a bigger drive.

One way to do this is to use an off-line secondary from your Replica Set. This should give you a whole maintenance window to migrate, repair, move back and bring back up.

If you are not running a Replica Set, it's time to look at doing just that.

Kirill Rakhman
  • 42,195
  • 18
  • 124
  • 148
Gates VP
  • 44,957
  • 11
  • 105
  • 108
  • 1
    Is this answer still valid as of now? – Tuan Anh Tran Jan 23 '16 at 07:55
  • 1
    Since this answer was posted, MongoDB has added WiredTiger for storing files. WiredTiger is far more efficient in terms of disk usage, however you cannot roll this out "in-place". So the above answers should still apply. – Gates VP Jan 23 '16 at 16:10
  • 1
    In modern versions of MongoDB (3.2+), the default storage engine is now WiredTiger. With WiredTiger you can use the [`compact` command](https://docs.mongodb.com/manual/reference/command/compact/) to try to free space in existing data files (if possible) during a maintenance window. The `repairDatabase` command is intended to be used to salvage/recover data and is not recommended in either MMAPv1 or WiredTiger as a strategy for reclaiming space. – Stennie Jun 06 '18 at 10:24
  • With MMAPv1 deleted space is freed as a result of rebuilding data files to salvage data, but that may result in data loss if there is any data file corruption. Assuming you have a replica set, re-syncing a replica set member is the recommended approach to reclaim disk space. If you repair a replica set member you may introduce data inconsistencies. See: [`db.repairDatabase()` behaviour](https://docs.mongodb.com/manual/reference/method/db.repairDatabase/#behavior). – Stennie Jun 06 '18 at 10:26
14

You could run the compact command on a single collection, or one by one in all the collections you want to shrink.

http://www.mongodb.org/display/DOCS/Compact+Command

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

As noted in comments, I was mistaken, compact does not actually reclaim disk space, it only defragments and rebuilds collection indexes.

Instead though, you could use "--repairpath" option if you have another drive available which has available freespace.

For example:

mongod --dbpath /data/db --repair --repairpath /data/db0

Shown here: http://docs.mongodb.org/manual/tutorial/recover-data-following-unexpected-shutdown/

EkoostikMartin
  • 6,831
  • 2
  • 33
  • 62
  • This doesn't actually reclaim disk space, I'm fairly certain. – Eve Freeman Jul 23 '12 at 18:11
  • Just a heads-up, according to the docs, `--repairpath` is, "only available for mongod instance using the MMAPv1 storage engine." https://docs.mongodb.com/manual/reference/program/mongod/#cmdoption--repairpath – Grinn Dec 13 '16 at 17:33
12

You can as well do a manual mongodump and mongorestore. That's basically the same what repairDatabase does. That way you can dump and restore it to/from a different machine with sufficient disk space.

udo
  • 1,486
  • 13
  • 18
  • +1 you can just write a script to do a mongodump/mongorestore on each node – Mihai Tomescu Aug 11 '14 at 18:55
  • 8
    THIS. Make sure to drop the db first before restoring it, to reclaim the space. Of course this option means a bit of downtime, but that's what 3AM is for! – CommaToast Sep 23 '14 at 20:18
3

If you're running a replica-set, you will want to issue a resync on each of your secondaries, one at a time. Once this has been completed, step-down your primary and resync the newly assigned secondary.

To resync, stop your mongod instance, delete the locals and start the process back up. Watch the logs to ensure everything starts back up properly and the resync has initiated.

If you have a lot of data / indexes, ensure your oplog is large enough, otherwise it's likely to go stale.

davissp14
  • 765
  • 4
  • 13
1

There is one other option, if you are using a replica set, but with a lot of caveats. You can fail over to another set member, then delete the files on the now former primary and do a full resync. A full resync rewrites the files from scratch in a similar way to a repair, but you will also have to rebuild indexes. This is not to be done lightly.

If you go down this path, my recommendation would be to have a 3 member replica set before doing this for disk space reclamation, so that at any time when a member is syncing from scratch you have 2 set members fully functional.

If you do not have a replica set, I recommend creating one, with two secondaries. When you sync them initially you will be creating a nice unfragmented and unpadded versions of your data. More here:

http://www.mongodb.org/display/DOCS/Replica+Set+Configuration

Adam Comerford
  • 21,336
  • 4
  • 65
  • 85