常见问题解答:MongoDB 存储

在本页面

本文档解决了有关 MongoDB 存储系统的常见问题。

Storage Engine 基础知识

什么是存储引擎?

存储引擎是数据库的一部分,负责 Management 如何在内存和磁盘上存储数据。许多数据库支持多个存储引擎,其中不同的引擎对于特定的工作负载性能更好。例如,一个存储引擎可能为读取大量工作负载提供更好的性能,而另一个可能为写入操作提供更高的吞吐量。

See also

Storage Engines

您可以在副本集中混合使用存储引擎吗?

是。您可以具有使用不同存储引擎的副本集成员。

设计这些多存储引擎部署时,请考虑以下事项:

WiredTiger 存储引擎

我可以将现有部署升级到 WiredTiger 吗?

Yes. See:

WiredTiger 提供多少压缩?

压缩数据与未压缩数据的比率取决于您的数据和使用的压缩库。默认情况下,WiredTiger 中的收集数据使用快照块压缩zlib压缩也是可用的。索引数据默认使用prefix compression

我应该将 WiredTiger 内部缓存设置为多大?

通过 WiredTiger,MongoDB 可以利用 WiredTiger 内部缓存和文件系统缓存。

从 MongoDB 3.4 开始,默认的 WiredTiger 内部缓存大小是以下两者中的较大者:

Note

在某些情况下,例如在容器中运行时,数据库的内存限制可能低于系统总内存。在这种情况下,此内存限制而不是系统总内存将用作最大可用 RAM。

要查看内存限制,请参阅hostInfo.system.memLimitMB

默认情况下,WiredTiger 对所有集合使用 Snappy 块压缩,对所有索引使用前缀压缩。压缩默认值是可以在全局级别配置的,也可以在收集和索引创建期间基于每个集合和每个索引进行设置。

WiredTiger 内部缓存中的数据与磁盘格式使用不同的表示形式:

通过文件系统缓存,MongoDB 自动使用 WiredTiger 缓存或其他进程未使用的所有可用内存。

要调整 WiredTiger 内部缓存的大小,请参见storage.wiredTiger.engineConfig.cacheSizeGB--wiredTigerCacheSizeGB。避免将 WiredTiger 内部缓存的大小增加到其默认值以上。

Note

storage.wiredTiger.engineConfig.cacheSizeGB限制了 WiredTiger 内部缓存的大小。os 将可用的可用内存用于文件系统缓存,从而允许压缩的 MongoDB 数据文件保留在内存中。此外,os 将使用任何可用的 RAM 来缓冲文件系统块和文件系统缓存。

为了容纳更多的 RAM 使用者,您可能必须减小 WiredTiger 内部缓存的大小。

默认的 WiredTiger 内部缓存大小值假定每台计算机只有一个mongod实例。如果一台机器包含多个 MongoDB 实例,则应减小设置以容纳其他mongod实例。

如果您在不能访问系统中所有可用 RAM 的容器(例如lxccgroups,Docker 等)中运行mongod,则必须将storage.wiredTiger.engineConfig.cacheSizeGB的值设置为小于该容器中可用 RAM 的值。容器。确切的数量取决于容器中运行的其他进程。参见memLimitMB

要查看有关缓存和逐出速率的统计信息,请参阅serverStatus命令返回的wiredTiger.cache字段。

WiredTiger 多久写入一次磁盘?

Note

如果writeConcernMajorityJournalDefault为 true,则写关注点"majority"表示j: true

如何在 WiredTiger 中回收磁盘空间?

WiredTiger 存储引擎在删除文档时会维护数据文件中的空记录列表。 WiredTiger 可以重用此空间,但是除非在非常特殊的情况下,否则不会将其返回给 os。

WiredTiger 可供重用的可用空间量反映在标题wiredTiger.block-manager.file bytes available for reuse下的db.collection.stats()的输出中。

为了使 WiredTiger 存储引擎将该空白空间释放给 os,可以对数据文件进行碎片整理。这可以使用compact命令来实现。有关其行为和其他注意事项的更多信息,请参见compact

MMAPv1 存储引擎

什么是内存 Map 文件?

内存 Map 文件是带有数据的文件,os 通过mmap()系统调用将其放置在内存中。因此mmap()将文件*Map 到虚拟内存区域。内存 Map 文件是 MongoDB 中 MMAPv1 存储引擎的关键部分。通过使用内存 Map 文件,MongoDB 可以将其数据文件的内容视为在内存中。这为 MongoDB 提供了一种非常快速,简单的方法来访问和处理数据。

内存 Map 文件如何工作?

MongoDB 使用内存 Map 文件来 Management 所有数据并与之交互。

内存 Map 将文件分配给具有直接逐字节关联的虚拟内存块。 MongoDB 内存在访问文档时将数据文件 Map 到内存。未访问的数据Map 到内存。

Map 后,文件和内存之间的关系使 MongoDB 可以像对待内存一样与文件中的数据进行交互。

MMAPv1 多久写入一次磁盘?

MMAPv1 存储引擎的默认配置中,MongoDB 每 60 秒写入一次磁盘上的数据文件,大约每 100 毫秒写入一次journal文件。

要更 Rewrite 入数据文件的间隔,请使用storage.syncPeriodSecs设置。有关日志文件,请参见storage.journal.commitIntervalMs设置。

这些值表示完成写操作到 MongoDB 写入数据文件或日记文件之间的“最大”时间量。在许多情况下,MongoDB 和 os 会更频繁地将数据刷新到磁盘,因此上述值代表理论上的最大值。

为什么我的数据目录中的文件大于数据库中的数据?

数据目录中的数据文件(默认配置为/data/db目录)可能大于插入数据库中的数据集。请考虑以下可能的原因:

预分配的数据文件

MongoDB 预分配其数据文件以避免文件系统碎片,因此,这些文件的大小并不一定反映您数据的大小。

storage.mmapv1.smallFiles选项将减小这些文件的大小,如果磁盘上有许多小型数据库,这可能会很有用。

The oplog

如果此mongod是副本集的成员,则数据目录包含oplog.rs文件,该文件是local数据库中的预分配capped collection

在 64 位安装中,默认分配约为磁盘空间的 5%。在大多数情况下,您无需调整操作日志的大小。有关更多信息,请参见Oplog Sizing

The journal

数据目录包含日志文件,这些日志文件在 MongoDB 将它们写入数据库之前将写操作存储在磁盘上。参见Journaling

Empty records

MMAPv1 存储引擎在删除文档和集合时会维护数据文件中的空记录列表。该空间可用于同一数据库中的新记录分配,但默认情况下,MMAPv1 不会将此空间返回给 os。

为了使 MMAPv1 存储引擎可以更有效地重用空 Logging 的空间,可以对数据进行碎片整理。要进行碎片整理,请使用compact命令。 compact需要最多 2 GB 的额外磁盘空间才能运行。如果磁盘空间严重不足,请不要使用compact。有关其行为和其他注意事项的更多信息,请参见compact

compact仅从集合中的 MongoDB 数据文件中删除碎片,并且不将任何磁盘空间返回给 os。要将磁盘空间返回给 os,请参阅如何回收磁盘空间?

如何回收磁盘空间?

Note

您无需为 MongoDB 回收磁盘空间即可重复使用释放的空间。有关释放空间的重复使用的信息,请参见Empty records

对于副本集的辅助成员,可以通过停止辅助成员重新同步,从成员的数据目录中删除所有数据和子目录并重新启动辅助成员来执行重新同步成员。有关详细信息,请参见重新同步副本集的成员

通过dropDatabase删除未使用的数据库也将删除关联的数据文件并释放磁盘空间。

什么是工作集?

工作集代表应用程序在正常操作过程中使用的数据整体。通常,这是总数据大小的一个子集,但是工作集的具体大小取决于数据库的实际使用情况。

如果运行要求 MongoDB 扫描集合中每个文档的查询,则工作集将扩展为包括每个文档。根据物理内存的大小,这可能导致工作集中的文档“页面输出”,或者被 os 从物理内存中删除。下一次 MongoDB 需要访问这些文档时,MongoDB 可能会导致硬页错误。

为了获得最佳性能,您的* active *集中的大多数应该适合 RAM。

什么是页面错误?

使用 MMAPv1 存储引擎时,由于 MongoDB 从其数据文件的当前不在物理内存中的部分读取数据或将数据写入其中的数据,可能会发生页面错误。相反,当物理内存用完并且物理内存的页面交换到磁盘时,就会发生 os 页面错误。

如果有可用内存,则 os 可以在磁盘上找到该页面并将其直接加载到内存中。但是,如果没有可用内存,则 os 必须:

在活动系统上,此过程可能会花费很长时间,尤其是与读取已在内存中的页面相比。

有关更多信息,请参见Page Faults

软页面错误和硬页面错误有什么区别?

带有 MMAP 存储引擎的 MongoDB 需要访问当前不在活动内存中的数据时,发生Page faults。 “硬”页面错误是指 MongoDB 必须访问磁盘才能访问数据的情况。相比之下,“软”页面错误仅将内存页面从一个列表移动到另一个列表,例如从 os 文件缓存中移动。

有关更多信息,请参见Page Faults

我可以手动填充文档以防止在更新过程中移动吗?

在 3.0.0 版中更改。

使用MMAPv1 存储引擎,如果文档增大,更新可能导致文档在磁盘上移动。为了最小化文档移动,MongoDB 使用padding

您不必手动填充,因为默认情况下,MongoDB 使用2 大小分配的幂添加padding automatically2 大小分配的幂确保 MongoDB 分配的文档空间大小为 2 的幂,这有助于确保 MongoDB 可以有效地重用由文档删除或重定位创建的可用空间,并在许多情况下减少重新分配的发生。

但是,如果必须手动填充文档,则可以向文档中添加一个临时字段,然后向该字段添加$unset,如下例所示。

Warning

请勿手动将文档放入加盖的集合中。将手动填充应用于具有上限的集合中的文档可能会中断复制。另外,如果您重新同步 MongoDB 实例,则不会保留填充。

var myTempPadding = [ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
                      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
                      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
                      "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"];

db.myCollection.insert( { _id: 5, paddingField: myTempPadding } );

db.myCollection.update( { _id: 5 },
                        { $unset: { paddingField: "" } }
                      )

db.myCollection.update( { _id: 5 },
                        { $set: { realField: "Some text that I might have needed padding for" } }
                      )

数据存储诊断

如何查看集合的大小?

要查看集合的统计信息,包括数据大小,请使用mongo shell 中的db.collection.stats()方法。以下示例对orders集合发出db.collection.stats()

db.orders.stats();

MongoDB 还提供以下方法来返回集合的特定大小:

以下脚本打印每个数据库的统计信息:

db.adminCommand("listDatabases").databases.forEach(function (d) {
   mdb = db.getSiblingDB(d.name);
   printjson(mdb.stats());
})

以下脚本打印每个数据库中每个集合的统计信息:

db.adminCommand("listDatabases").databases.forEach(function (d) {
   mdb = db.getSiblingDB(d.name);
   mdb.getCollectionNames().forEach(function(c) {
      s = mdb[c].stats();
      printjson(s);
   })
})

如何检查集合的各个索引的大小?

要查看分配给每个索引的数据大小,请使用db.collection.stats()方法并检查返回文档中的indexSizes字段。

如果索引使用前缀压缩(即默认为 WiredTiger),则该索引的返回大小将反映压缩后的大小。

如何获取有关数据库存储使用的信息?

mongo Shell 中的db.stats()方法返回“活动”数据库的当前状态。有关返回字段的描述,请参见dbStats Output

首页