【问题标题】:Reducing MongoDB database file size减少 MongoDB 数据库文件大小
【发布时间】:2010-06-03 14:05:37
【问题描述】:

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

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

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

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

【问题讨论】:

  • 这个问题是否被认为已回答?我们需要更多数据吗?
  • 从2.8版本开始,可以compress your data,大大节省空间。
  • 我遇到了同样的挑战,最简单的解决方法是使用 copyDatabase() 函数复制数据库,然后复制到原始数据库 db.dropDatabase() 然后复制数据库恢复原位。我的数据库大部分是空的,当我复制时,只复制了实际可用的数据。删除原始数据库删除了大文件。使用 db.repairDatabase() 不是一个选项,因为我的服务器的磁盘空间已经很低,并且此操作将需要非常大量的可用空间,远远超过此操作所需的空间。

标签: mongodb


【解决方案1】:

更新:使用compact 命令 WiredTiger 它看起来像extra disk space will actually be released to the OS


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

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


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

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

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

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

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

目前没有使用 Mongo 来“就地压缩”的好方法。而且Mongo绝对可以吸纳很多空间。

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

【讨论】:

  • 感谢盖茨副总裁的回答。我在考虑你提到的两个选项。但在做这些事情之前,我想知道是否有一个紧凑的就地解决方案可用。再次感谢。
  • 截至今天 (2010-11-18) Dwight(在华盛顿特区的 MongoDC 活动上发言)推荐了复制 / --repair / 切换方法,如果您想在不占用数据库的情况下进行压缩离线。
  • 只是提醒“不要像我那样做”并以 root 身份运行 --repair。将 db 文件 chowns 到 root。呵呵。
  • 'compact' 的文档说:“此操作不会减少文件系统上使用的磁盘空间量。”我不明白这是如何解决原始问题的。
  • 如果您查看原始问题,部分问题涉及数据过多而无法执行修复。如果您用一个 DB 填充了 2/3 的驱动器,则无法执行修复。在新数据库完全“复制和修复”之前,新分配的文件会占用剩余空间,并且永远不会发生“切换”。使用compact,他至少可以保留现有文件。我同意,这不是一个完整的解决方案,而是一个渐进式的改进。
【解决方案2】:

看起来 Mongo v1.9+ 已经支持 compact 了!

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

在此处查看文档:http://docs.mongodb.org/manual/reference/command/compact/

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

【讨论】:

  • @AnujGupta "repairDatabase 命令压缩数据库中的所有集合。它与单独对每个集合运行 compact 命令相同。" docs.mongodb.org/manual/reference/command/repairDatabase/…。因此,如果repairDatabase 减小大小以便紧凑。我每周都会通过大量删除和更新来压缩我的收藏。比起repariDatabase,我更喜欢compact,因为首先它针对的是你想要的集合,而不是整个数据库。其次,它只需要 2GB 可用空间,而不是 db 文件大小的 x2(在我的情况下为 500GB)。
  • 顺便说一句:" MongoDB 提供了 2 种不同的方法来压缩数据并恢复最佳性能:repairDatabase 和 compact。如果您的数据库相对较小,或者您可以负担一个节点,RepairDatabase 是合适的很长一段时间没有轮换。 对于我们的数据库大小和查询工作负载,对我们所有的集合运行连续压缩更有意义。” blog.parse.com/2013/03/26/always-be-compactinggithub.com/ParsePlatform/Ops/blob/master/tools/mongo_compact.rb
  • @Maziyar docs.mongodb.org/manual/reference/command/compact/#disk-space - “与 repairDatabase 不同,compact 不会释放文件系统上的空间”。
  • @Maziyar OP 希望释放未使用的空间,这是通过repairDatabase 而不是compact 实现的。 compact 不会释放空间,它只会对已用完的空间进行碎片整理,不会减少空间。
  • 从 mongo 3.0 开始,如果使用 WiredTiger 存储引擎,compact 回收空间。
【解决方案3】:

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

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

【讨论】:

  • 断言:15936 创建集合 db.collection 失败。 Errmsg:异常:指定大小: 当上限为真时
  • :看起来像 ubuntu 回归...转储文件的元数据已封顶:“未定义”...删除这些修复了导入问题。
  • 我的数据库几乎已经对整个磁盘进行了评分。它是 120 GB(磁盘 160 GB)紧凑型不会减小文件大小,并且由于空间不足,无法使用 repairDatabase。在数据库的 mongodump & dropDatabase & mongorestore 之后,我有 40 GB 的数据库大小。
  • 对restore命令的小修正mongorestore --db databasename dump/databasename
【解决方案4】:

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

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

【讨论】:

    【解决方案5】:

    如果您需要运行完整修复,请使用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
    

    【讨论】:

    • 这很好用。我缺乏修复所需的 2 倍空间,所以我安装了 NAS。唯一的问题,它需要 18 个小时才能完成,但它确实有效。确保添加 --nojoural 标志。
    【解决方案6】:

    2.8 version of Mongo, you can use compression 开头。使用 WiredTiger 引擎,mmap 将有 3 级压缩(2.6 中默认不提供压缩):

    这是一个示例,说明您可以为 16 GB 的数据节省多少空间:

    数据取自this文章。

    【讨论】:

      【解决方案7】:

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

      1. MMAP() 引擎:

      命令:db.repairDatabase()

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

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

      2。连线老虎: 它会自动自行解决。

      【讨论】:

        【解决方案8】:

        在 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 命令可以更准确地描述为“打捞数据库”。也就是说,它通过丢弃损坏的文档来重新创建数据库,以尝试使数据库进入可以启动它并从中挽救完整文档的状态。

        在 MMAPv1 部署中,数据库文件的这种重建会为操作系统释放空间作为副作用。向操作系统释放空间从来都不是目的。

        repairDatabase 在副本集上的后果

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

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

        更糟糕的是,这种情况完全有可能长期处于休眠状态,只是突然袭击而没有明显的原因。

        【讨论】:

          【解决方案9】:

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

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

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

          MMAPv1

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

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

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

          WiredTiger

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

          压缩进程将空闲空间释放给操作系统。 运行压缩操作需要最少的磁盘空间。 WiredTiger 还阻塞了对数据库的所有操作,因为它需要数据库级锁定。

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

          db.runCommand({repairDatabase: 1})
          

          【讨论】:

            【解决方案10】:

            Mongodb 3.0 及更高版本有一个新的存储引擎——WiredTiger。 在我的例子中,切换引擎将磁盘使用量从 100 Gb 减少到 25 Gb。

            【讨论】:

              【解决方案11】:

              无法缩小数据库文件的大小。在“修复”数据库时,mongo 服务器只能删除它的一些文件。如果大量数据被删除,mongo server 会在修复过程中“释放”(delete)它的一些现有文件。

              【讨论】:

                【解决方案12】:

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

                【讨论】:

                  【解决方案13】:

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

                  mongod --repair
                  

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

                  【讨论】:

                    【解决方案14】:

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

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

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

                    【讨论】:

                      【解决方案15】:

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

                      如果使用replica set sharded cluster,使用compact 命令,它将对所有集合的所有数据和索引文件进行重写和碎片整理。 语法:

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

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

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

                      【讨论】:

                        【解决方案16】:

                        这只是我能够做到的一种方式。不保证您现有数据的安全性。风险自负。

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

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

                        如果您的数据库中没有重要的数据,这似乎是一种更简单的方法。

                        【讨论】:

                        • 文件存储为 . 例如mydb.3 - 你不能告诉集合。
                        猜你喜欢
                        • 2018-01-31
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2020-04-23
                        • 2013-01-07
                        • 2016-11-11
                        • 2013-06-25
                        • 2011-01-10
                        相关资源
                        最近更新 更多