自动压缩mongodb中删除的空间?

这个mongodb文件说

为了压缩这个空间,从mongo shell运行db.repairDatabase()(注意这个操作会阻塞并且很慢)。

在http://www.mongodb.org/display/DOCS/Excessive+Disk+Space

我不知道如何自动删除mongodb磁盘空间?

ps在mongodb存储了多达20GB的下载任务,在半小时内完成了。

一般来说,如果你不需要缩小你的数据文件,你不应该缩小它们。 这是因为将数据文件“增长”到磁盘上是一个相当昂贵的操作,MongoDB可以在数据文件中分配的空间越less,碎片就越less。

所以,你应该尽量为数据库提供尽可能多的磁盘空间。

但是,如果你必须缩小数据库,你应该记住两点。

  1. MongoDB的数据文件翻倍,因此数据文件可能是64MB,然后是128MB等等,最高可达2GB(在这一点上,文件会停止翻倍,直到2GB)。

  2. 和大多数数据库一样…做缩小的操作,你需要安排一个单独的工作,MongoDB中没有“autoshrink”。 事实上主要的noSQL数据库(讨厌这个名字)只有Riak会autoshrink。 因此,您需要使用您的操作系统的调度程序来创build一个作业来运行缩小。 你可以使用一个bash脚本,或者让一个工作运行一个php脚本等。

Serverside Javascript

你可以使用服务器端的Javascript做缩小,并通过定期的基地通过工作(如cron或Windows调度服务)通过mongo的shell运行JS …

假设一个名为foo的集合,您可以将下面的javascript保存到名为bar.js的文件中,然后运行…

$ mongo foo bar.js 

JavaScript文件看起来像…

 // Get a the current collection size. var storage = db.foo.storageSize(); var total = db.foo.totalSize(); print('Storage Size: ' + tojson(storage)); print('TotalSize: ' + tojson(total)); print('-----------------------'); print('Running db.repairDatabase()'); print('-----------------------'); // Run repair db.repairDatabase() // Get new collection sizes. var storage_a = db.foo.storageSize(); var total_a = db.foo.totalSize(); print('Storage Size: ' + tojson(storage_a)); print('TotalSize: ' + tojson(total_a)); 

这将运行并返回像…

 MongoDB shell version: 1.6.4 connecting to: foo Storage Size: 51351 TotalSize: 79152 ----------------------- Running db.repairDatabase() ----------------------- Storage Size: 40960 TotalSize: 65153 

按计划运行(在非繁忙时间),你很好。

封顶的集合

然而,还有一个选项, 封顶的collections 。

Capped集合是固定大小的集合,具有非常高性能的自动FIFO超时function(超时基于插入顺序)。 如果您熟悉这一点,它们有点像“RRD”概念。

另外,高性能的自动封顶集合可以维护集合中对象的插入顺序; 这对于某些使用情况(如日志logging)非常有用。

基本上,你可以限制一个集合的大小(或者文档的数量)来表示.. 20GB,一旦达到这个限制,MongoDB将开始抛出最老的logging,并且在它们进来时用新的条目replace它们。

这是保存大量数据的好方法,随着时间的推移丢弃较旧的数据并保持相同数量的磁盘空间。

我有另一个解决scheme可能比db.repairDatabase()更好的工作,如果你不能负担系统被locking,或没有双重存储。

您必须使用副本集。

我的想法是,一旦你已经删除了吞噬你的磁盘的所有多余的数据,停止一个辅助副本,擦除它的数据目录,启动它,让它重新同步主。

这个过程非常耗时,但是在执行rs.stepDown()时,它只需要花费几秒钟的停机时间。

这也不能自动化。 那可以,但我不认为我愿意尝试。

运行db.repairDatabase()将要求您的空间等于文件系统上可用数据库的当前大小。 当您知道数据库中保留的集合或数据将保留在数据库中的空间比分配的空间less得多,并且您没有足够的空间进行修复时,这可能会很麻烦。

作为一个替代scheme,如果您的数据库很less,您实际上需要保留或只需要一部分数据,那么您可以将需要保留的数据移动到新数据库中,然后删除旧数据库。 如果您需要相同的数据库名称,则可以通过相同的名称将它们移回到新的数据库中。 只要确保你重新创build任何索引。

 use cleanup_database db.dropDatabase(); use oversize_database db.collection.find({},{}).forEach(function(doc){ db = db.getSiblingDB("cleanup_database"); db.collection_subset.insert(doc); }); use oversize_database db.dropDatabase(); use cleanup_database db.collection_subset.find({},{}).forEach(function(doc){ db = db.getSiblingDB("oversize_database"); db.collection.insert(doc); }); use oversize_database <add indexes> db.collection.ensureIndex({field:1}); use cleanup_database db.dropDatabase(); 

具有多个集合的数据库的导出/删除/导入操作可能会达到相同的结果,但我没有经过testing。

此外,作为一项政策,您可以将永久性collections与暂时/处理数据保存在单独的数据库中,并在作业完成后立即删除处理数据库。 由于MongoDB是无模式的,除了索引之外,没有任何东西会丢失,并且在下一次运行进程的插入时,将重新创build数据库和集合。 只要确保你的工作包括在适当的时间创build任何nessecary索引。

如果您正在使用副本集 (最初编写此问题时不可用),则可以设置一个自动回收空间的过程,而不会造成明显的中断或性能问题。

为此,您可以利用副本集中辅助节点的自动初始同步function。 为了解释:如果closures辅助节点,擦除其数据文件并重新启动辅助节点,辅助节点将从集合中的其他节点重新同步(默认情况下,通过查看ping响应来select距离节点最近的节点次)。 当这种重新同步发生时,所有的数据都是从头开始重写的(包括索引),有效地完成了修复和回收的磁盘空间。

通过在辅助节点上运行(然后降低主节点并重复该过程),可以有效地回收整个集合中的磁盘空间,同时最大限度地减less中断。 如果你正在从辅助阅读中学习,那么你需要小心,因为这可能需要很长一段时间。 你也想确保你的oplog窗口足以做一个成功的重新同步,但是这通常是你想要确保你是否做这件事。

要使这个过程自动化,您只需要运行一个脚本即可在单独的日子(或类似的日子)为您的设置的每个成员执行此操作,最好是在安静的时间或维护时段内执行此操作。 这个脚本的一个非常天真的版本会在bash看起来像这样:

注意:这基本上是伪码 – 仅用于说明目的 – 不要用于没有显着变化的生产系统

 #!/bin/bash # First arg is host MongoDB is running on, second arg is the MongoDB port MONGO=/path/to/mongo MONGOHOST=$1 MONGOPORT=$2 DBPATH = /path/to/dbpath # make sure the node we are connecting to is not the primary while (`$MONGO --quiet --host $MONGOHOST --port $MONGOPORT --eval 'db.isMaster().ismaster'`) do `$MONGO --quiet --host $MONGOHOST --port $MONGOPORT --eval 'rs.stepDown()'` sleep 2 done echo "Node is no longer primary!\n" # Now shut down that server # something like (assuming user is set up for key based auth and has password-less sudo access a la ec2-user in EC2) ssh -t user@$MONGOHOST sudo service mongodb stop # Wipe the data files for that server ssh -t user@$MONGOHOST sudo rm -rf $DBPATH ssh -t user@$MONGOHOST sudo mkdir $DBPATH ssh -t user@$MONGOHOST sudo chown mongodb:mongodb $DBPATH # Start up server again # similar to shutdown something like ssh -t user@$MONGOHOST sudo service mongodb start