减少MongoDB数据库文件的大小

时间:2010-06-03 14:05:38

标签: mongodb

我有一个曾经很大的MongoDB数据库(> 3GB)。从那时起,文档已被删除,我希望数据库文件的大小相应减少。

但是由于MongoDB保留了分配的空间,因此文件仍然很大。

我在这里和那里读到,admin命令mongod --repair用于释放未使用的空间,但我没有足够的空间来运行此命令。

你知道我可以释放闲置空间吗?

15 个答案:

答案 0 :(得分:144)

使用compact命令 WiredTiger

更新:,它看起来像extra disk space will actually be released to the OS


UPDATE:从v1.9开始+有一个compact命令。

此命令将执行“内联”压缩。它仍然需要一些额外的空间,但不是那么多。


MongoDB通过以下方式压缩文件:

  • 将文件复制到新位置
  • 循环浏览文档并重新排序/重新解决它们
  • 用新文件替换原始文件

您可以通过运行mongod --repair或直接连接并运行db.repairDatabase()来执行此“压缩”。

在任何一种情况下,您都需要在某处复制文件的空间。现在我不知道为什么你没有足够的空间来执行压缩,但是,如果你有另一台有更多空间的计算机,你确实有一些选择。

  1. 将数据库导出到安装了Mongo的另一台计算机(使用mongoexport),然后您可以导入同一个数据库(使用mongoimport)。这将导致更加压缩的新数据库。现在,您可以使用新的数据库文件停止原始mongod替换,并且您可以继续使用。
  2. 停止当前的mongod并将数据库文件复制到更大的计算机并在该计算机上运行修复。然后,您可以将新数据库文件移回原始计算机。
  3. 目前还没有一种使用Mongo“紧凑到位”的好方法。 Mongo绝对可以占用很多空间。

    现在压缩的最佳策略是运行主从设置。然后你可以压缩奴隶,让它赶上并切换它们。我知道还有点毛茸茸的。也许Mongo团队会提出更好的压实,但我不认为它在他们的名单上很高。目前假设驱动器空间很便宜(通常是这样)。

答案 1 :(得分:37)

我遇到了同样的问题,只需在命令行执行此操作即可解决:

mongodump -d databasename
echo 'db.dropDatabase()' | mongo databasename
mongorestore dump/databasename

答案 2 :(得分:31)

看起来Mongo v1.9 +已经支持紧凑型了!

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

请参阅此处的文档:http://docs.mongodb.org/manual/reference/command/compact/

“与repairDatabase不同,compact命令不需要双磁盘空间来完成它的工作。它在工作时需要少量的额外空间。另外,compact更快。”

答案 3 :(得分:14)

压缩当前数据库中的所有集合

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

答案 4 :(得分:13)

如果您需要进行完整修复,请使用repairpath选项。将其指向具有更多可用空间的磁盘。

例如,在我的Mac上我使用过:

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

更新:根据MongoDB Core Server Ticket 4266,您可能需要添加--nojournal以避免错误:

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

答案 5 :(得分:11)

2.8 version of Mongo, you can use compression开始。你将使用WiredTiger引擎进行3级压缩,mmap(默认情况下2.6不提供压缩):

以下是您可以为16 GB数据保存多少空间的示例:

enter image description here

数据来自this文章。

答案 6 :(得分:7)

我们需要基于StorageEngine解决2种方法。

<强> 1。 MMAP()引擎:

命令: db.repairDatabase()

注意: repairDatabase需要的可用磁盘空间等于当前数据集的大小加上2千兆字节。如果保存dbpath的卷缺少足够的空间,则可以装入单独的卷并将其用于修复。为repairDatabase安装单独的卷时,必须从命令行运行repairDatabase,并使用--repairpath开关指定用于存储临时修复文件的文件夹。 例如:想象数据库大小为120 GB意味着,(120 * 2)+2 = 242 GB所需的硬盘空间。

另一种收集方式, 命令: db.runCommand({compact:&#39; collectionName&#39;})

<强> 2。 WiredTiger:          它自动解决了它自己。

答案 7 :(得分:4)

如果从集合中删除了大量数据,并且集合从不将删除的空间用于新文档,则需要将此空间返回到操作系统,以便其他数据库或集合可以使用它。您需要运行压缩或修复操作,以便对磁盘空间进行碎片整理并重新获得可用空间。

压缩过程的行为取决于MongoDB引擎,如下所示

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

<强> MMAPv1

压缩操作对数据文件进行碎片整理&amp;索引。但是,它不会释放操作系统的空间。该操作对于碎片整理和创建更多连续空间以供MongoDB重用仍然有用。但是,当可用磁盘空间非常低时,它没有用。

在压缩操作期间,需要额外的磁盘空间,最多2GB。

在压缩操作期间保持数据库级锁定。

<强> WiredTiger

WiredTiger引擎默认提供压缩,比MMAPv1消耗更少的磁盘空间。

紧凑型进程释放了操作系统的可用空间。 运行压缩操作需要最小的磁盘空间。 WiredTiger还会阻止数据库上的所有操作,因为它需要数据库级锁定。

对于 MMAPv1 引擎,compact doest不会将空间返回给操作系统。您需要运行修复操作以释放未使用的空间。

db.runCommand({repairDatabase: 1})

答案 8 :(得分:4)

MongoDB中的空间回收存在一些相当大的混淆,一些推荐的做法在某些部署类型中是非常危险的。更多详情如下:

TL; DR repairDatabase尝试从试图从磁盘损坏中恢复的独立MongoDB部署中抢救数据。如果它恢复空间,则纯粹是副作用。恢复空间永远不应该是运行repairDatabase的主要考虑因素。

恢复独立节点中的空间

WiredTiger:对于具有WiredTiger的独立节点,运行compact将释放操作系统空间,但需要注意一点:MongoDB 3.0.x上WiredTiger上的compact命令受此错误的影响:SERVER-21833已在MongoDB 3.2.3中修复。在此版本之前,WiredTiger上的compact可能会无声地失败。

MMAPv1:由于MMAPv1的工作方式,使用MMAPv1存储引擎没有安全且受支持的方法来恢复空间。 MMAPv1中的compact将对数据文件进行碎片整理,可能为新文档提供更多可用空间,但不会将空间释放回操作系统。

如果您完全了解此潜在危险命令(见下文)的后果,可能能够运行repairDatabase,因为repairDatabase基本上通过丢弃损坏的文档来重写整个数据库。作为副作用,这将创建新的MMAPv1数据文件,而不会产生任何碎片,并将空间释放回操作系统。

对于不太冒险的方法,在MMAPv1部署中也可以运行mongodumpmongorestore,具体取决于部署的大小。

恢复副本集中的空间

对于副本集配置,恢复空间的最佳和最安全的方法是为WiredTiger和MMAPv1执行initial sync

如果需要从集合中的所有节点恢复空间,则可以执行滚动初始同步。也就是说,在最后逐步降低主要并在其上执行初始同步之前,在每个辅助节点上执行初始同步。滚动初始同步方法是执行副本集维护的最安全方法,它也不会将停机时间作为奖励。

请注意,执行滚动初始同步的可行性还取决于部署的大小。对于非常大的部署,执行初始同步可能不太可行,因此您的选项稍微有限。如果使用了WiredTiger,则可能能够从该集合中取出一个辅助节点,以独立方式启动它,在其上运行compact,然后将其重新加入该集合。

关于repairDatabase

请不要在副本集节点上运行repairDatabase 。这非常危险,如repairDatabase page中所述,并在下面详细介绍。

名称repairDatabase有点误导,因为命令不会尝试修复任何内容。该命令旨在在独立节点上出现磁盘损坏时使用,这可能导致文档损坏。

repairDatabase命令可以更准确地描述为&#34;打捞数据库&#34;。也就是说,它通过丢弃损坏的文档来重新创建数据库,以试图让数据库进入一个可以启动它并从中挽救完整文档的状态。

在MMAPv1部署中,重建数据库文件会将操作系统的空间释放为副作用。释放操作系统的空间绝不是目的。

repairDatabase对副本集

的后果

在副本集中,MongoDB期望集合中的所有节点都包含相同的数据。如果在副本集节点上运行repairDatabase,则该节点可能包含未检测到的损坏,repairDatabase将尽职地删除损坏的文档。

可以预见,这使得该节点包含与集合其余部分不同的数据集。如果更新恰好击中该单个文档,整个集合可能会崩溃。

更糟糕的是,这种情况完全有可能长时间处于休眠状态,只是在没有明显原因的情况下突然发作。

答案 9 :(得分:3)

Mongodb 3.0及更高版本有一个新的存储引擎--WiredTiger。 在我的情况下,交换引擎将磁盘使用量从100 Gb减少到25 Gb。

答案 10 :(得分:1)

数据库文件的大小不能减小。在“修复”数据库时,mongo服务器只能删除其中的一些文件。如果删除了大量数据,mongo服务器将在修复期间“释放”(删除)一些现有文件。

答案 11 :(得分:1)

一般来说,compact比repairDatabase更可取。但是,修复compact的一个优点是可以对整个集群进行修复。紧凑,你必须登录每个碎片,这有点烦人。

答案 12 :(得分:0)

在分片群集的情况下,不建议使用mongoDB -repair。

如果使用副本集分片群集,请使用紧凑命令,它将重写和整理所有集合的所有数据和索引文件。 语法:

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

当与force:true一起使用时,compact在副本集的主副本上运行。 例如 db.runCommand ( { command : "collection_name", force : true } )

要考虑的其他要点: -它阻止了操作。因此建议在维护窗口中执行。 -如果副本集在不同的服务器上运行,则需要分别在每个成员上执行 -对于分片群集,压缩需要分别在每个分片成员上执行。无法针对mongos实例执行。

答案 13 :(得分:0)

对于独立模式,您可以使用压缩或修复,

对于分片群集或副本集,以我的经验,在主数据库上运行压缩,然后在辅助数据库上压缩之后,主数据库的大小减小了,但没有减小。 您可能需要执行resync member来减少辅助数据库的大小。通过这样做,您可能会发现辅助数据库的大小甚至比主数据库减小了很多,我猜这个compact命令并没有真正压缩集合。 因此,我结束了switching the primary and secondary of the replica set,然后再次做resync member

我的结论是,减小分片/副本集大小的最佳方法是执行重新同步成员,切换主从节点并再次重新同步。

答案 14 :(得分:-5)

只有一种方式,我能够做到这一点。不保证现有数据的安全性。尝试自己承担风险。

直接删除数据文件并重启mongod。

例如,使用ubuntu(数据的默认路径:/ var / lib / mongodb),我有几个文件的名称如:collection。#。我保留了collection.0并删除了所有其他内容。

如果您在数据库中没有严重的数据,似乎更容易。