减少MongoDB数据库文件大小


165

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

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

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

您知道我可以释放未使用空间的方法吗?


7
这个问题被认为已经回答了吗?我们需要更多数据吗?
盖茨副总裁

2
从2.8版本开始,您可以压缩数据,从而节省大量空间。
萨尔瓦多·达利

1
我也面临同样的挑战,解决它的最简单方法是使用copyDatabase()函数复制数据库,然后复制到原始数据库db.dropDatabase(),然后将数据库复制回原位。我的数据库几乎是空的,当我进行复制时,仅复制了实际可用的数据。删除原始数据库将删除大文件。不能使用db.repairDatabase(),因为我的服务器的磁盘空间已经很低,并且此操作将需要非常大的可用空间,远远超出了此操作的必要。
user3892260

Answers:


144

更新:使用compact命令 WiredTiger,看起来多余的磁盘空间实际上将释放到OS


更新:从v1.9 +开始,有一个compact命令。

该命令将执行“在线压缩”。它仍然需要一些额外的空间,但并不需要那么多。


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

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

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

无论哪种情况,您都需要在某个地方复制文件。现在,我不知道为什么您没有足够的空间来执行压缩,但是,如果您有一台具有更多空间的计算机,您确实可以选择。

  1. 将数据库导出到安装了Mongo的另一台计算机上(使用mongoexport),然后可以导入同一数据库(使用mongoimport)。这将导致新数据库的压缩程度更高。现在,您可以停止mongod使用新的数据库文件进行原始替换了,一切顺利。
  2. 停止当前mongod,然后将数据库文件复制到更大的计算机上,然后在该计算机上运行修复程序。然后,您可以将新的数据库文件移回原始计算机。

当前没有使用Mongo进行“紧凑压缩”的好方法。而且Mongo绝对可以占用很多空间。

目前最好的压缩策略是运行主从设置。然后,您可以压缩从站,让它赶上并切换它们。我知道还是有点毛。也许Mongo团队会提出更好的就地压实,但我认为这并不在他们的榜单上。当前假定驱动器空间便宜(通常是便宜的)。


感谢盖茨副总裁的回答。我在想你提到的两个选择。但是在做这些事情之前,我想知道是否有紧凑的就地解决方案。再次感谢。
Meuble 2010年

3
从今天开始(2010-11-18),Dwight(在华盛顿特区的MongoDC活动上发表演讲)建议,如果要压缩而不使数据库脱机,则采用复制/-修复/切换方法。
David J.

10
只是抬起头,“不要像我一样做”并以root身份运行--repair。将数据库文件切成根。h
龙猫

18
'compact'的文档说:“此操作不会减少文件系统上使用的磁盘空间量。” 我不明白这是如何解决原始问题的。
Ed Norris

如果您查看原始问题,则问题的一部分涉及拥有太多数据以进行修复。如果您用一个数据库填充了驱动器的2/3,则无法进行修复。新分配的文件将在完全“复制和修复”新数据库之前占用剩余空间,并且“切换”将永远不会发生。使用compact,他至少可以保留现有文件。我同意,这不是一个完整的解决方案,但它是逐步的改进。
盖茨副总裁

39

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

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

断言:15936创建集合db.collection失败。Errmsg:例外:当上限为true时,指定大小:<n>
tweak2 2013年

:看起来像ubuntu回归...转储文件中的元数据已设置上限:“未定义” ...删除这些内容可修复导入问题。
tweak2 2013年

2
我的数据库几乎对整个磁盘进行了评分。它的大小为120 GB(磁盘160 GB)。该紧凑型计算机无法减小文件大小,并且由于缺少空间而无法使用repairDatabase。在数据库的mongodump和dropDatabase&mongorestore之后,我有40 GB的数据库大小。
伊戈尔·贝尼科夫

对恢复命令的小更正mongorestore --db databasename dump/databasename
JERRY

34

看来Mongo v1.9 +已支持紧凑版!

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

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

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


3
” @AnujGupta“ repairDatabase命令压缩数据库中的所有集合。这与在每个集合上单独运行compact命令相同。docs.mongodb.org/manual/reference/command/repairDatabase/…。因此,如果repairDatabase减小了尺寸以使其紧凑。我一直在压缩我的收藏集,每周进行大量删除和更新。我比repariDatabase更喜欢压缩,因为它首先针对的是您想要的集合,而不是整个数据库。其次,它只需要2GB的可用空间,而不是数据库文件大小的2倍(在我的情况下为500GB)。
Maziyar 2013年

1
顺便说一句,请检查一下:“ MongoDB提供了两种压缩数据并恢复最佳性能的方法:repairDatabase和compact。如果数据库相对较小,或者您可以承受很长一段时间不让节点旋转,则RepairDatabase是合适的对于我们的数据库大小和查询工作量,对所有集合运行连续压缩更为有意义。” blog.parse.com/2013/03/26/always-be-compacting github.com/ParsePlatform/Ops/blob/master/tools/mongo_compact.rb
Maziyar,2013年

3
@Maziyar docs.mongodb.org/manual/reference/command/compact/#disk-space- “与repairDatabase不同,compact不会释放文件系统上的空间”。
阿努·古普塔

4
@Maziyar OP希望释放未使用的空间,这是通过repairDatabase而不是通过实现的compactcompact不会释放空间,只会对已用完的空间进行碎片整理,而不会减少空间。
Anuj Gupta 2014年

5
从mongo 3.0开始,如果使用WiredTiger存储引擎,compact 回收空间。
加里

19

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

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

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

1
这很棒。我缺少就地维修所需的2倍空间,因此我安装了NAS。唯一的问题是,它花了18个小时才完成,但确实奏效了。确保添加--nojoural标志。
zenocon


7

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

1. MMAP()引擎:

命令:db.repairDatabase()

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

另一种明智的收集方式,命令: db.runCommand({compact:'collectionName'})

2. WiredTiger: 它会自动自行解决。


6

在MongoDB中,对于空间回收存在一些相当大的困惑,并且在某些部署类型中,某些建议的做法非常危险。以下是更多详细信息:

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

恢复独立节点中的空间

WiredTiger:对于具有WiredTiger的独立节点,运行compact将释放空间到操作系统,但有一个警告:compact在MongoDB 3.0.x上的WiredTiger上的命令受到以下错误的影响:SERVER-21833,该错误已在MongoDB 3.2.3中修复。在此版本之前,compactWiredTiger可能会静默失败。

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

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

对于冒险性较低的方法,根据部署的大小,在MMAPv1部署中也可以运行mongodump和运行mongorestore

恢复副本集中的空间

对于副本集配置,恢复空间的最佳和最安全的方法是对WiredTiger和MMAPv1 执行初始同步

如果需要从集合中的所有节点恢复空间,则可以执行滚动初始同步。也就是说,在最终退出主节点并对其进行初始同步之前,请对每个辅助节点执行初始同步。滚动初始同步方法是执行副本集维护的最安全方法,并且不涉及停机时间。

请注意,进行滚动初始同步的可行性还取决于部署的大小。对于超大型部署,进行初始同步可能不可行,因此您的选择受到更多限制。如果使用了WiredTiger,可以从集合中取出一个辅助副本,以独立版本启动它,然后compact在其上运行,然后将其重新加入到集合中。

关于 repairDatabase

请不要repairDatabase在副本集节点上运行。如repairDatabase页面中所述,并在下面进行更详细的描述,这非常危险。

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

repairDatabase命令可以更准确地描述为“救助数据库”。也就是说,它通过丢弃损坏的文档来重新创建数据库,以使数据库进入可以启动数据库并从中回收完整文档的状态。

在MMAPv1部署中,这种数据库文件的重建为OS释放了空间,这是一个副作用。向操作系统释放空间绝不是目的。

repairDatabase副本集上的后果

在副本集中,MongoDB希望该集中的所有节点都包含相同的数据。如果您repairDatabase在副本集节点上运行,则该节点有可能包含未检测到的损坏,并repairDatabase会忠实地为您删除损坏的文档。

可以预见,这将使该节点包含与该集合其余部分不同的数据集。如果有更新发生在单个文档上,则整个文档集可能会崩溃。

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


5

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

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

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

MMAPv1

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

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

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

有线老虎

默认情况下,WiredTiger引擎提供压缩,该压缩比MMAPv1占用更少的磁盘空间。

紧凑的过程将可用空间释放给操作系统。运行压缩操作需要最少的磁盘空间。WiredTiger还需要对数据库进行级别锁定,从而阻止了对数据库的所有操作。

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

db.runCommand({repairDatabase: 1})

3

Mongodb 3.0及更高版本具有新的存储引擎-WiredTiger。以我为例,交换引擎将磁盘使用量从100 Gb减少到25 Gb。


1

数据库文件的大小无法减小。在“修复”数据库时,mongo服务器只能删除其某些文件。如果已删除大量数据,则mongo服务器将在修复过程中“释放”(删除)其某些现有文件。


1

一般而言,紧凑型优于repairDatabase。但是,与紧凑型相比,修复的一个优势是您可以对整个群集进行修复。紧凑,您必须登录到每个分片,这很烦人。


1

当我遇到同样的问题时,我停止了mongo服务器,然后使用命令再次启动它

mongod --repair

在运行修复操作之前,您应该检查硬盘上是否有足够的可用空间(最小值-是数据库的大小)


1

对于独立模式,您可以使用紧凑型或维修型,

对于分片群集或副本集,以我的经验,在主数据库上运行压缩,然后在辅助数据库上压缩之后,主数据库的大小减小了,但辅助数据库没有减小。您可能想要执行重新同步成员以减小辅助数据库的大小。通过这样做,您可能会发现辅助数据库的大小甚至比主数据库减小了很多,我猜这个compact命令并没有真正压缩集合。因此,我最终切换了副本集的主副本和辅助副本,并再次进行了重新同步成员

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


0

如果是分片群集,建议不要使用mongoDB -repair。

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

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

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

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


-5

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

直接删除数据文件,然后重新启动mongod。

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

如果您在数据库中没有大量数据,似乎是一种更简单的方法。


文件存储为<database_name>。<number>,例如mydb.3-您无法告诉集合。
bobmarksie
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.