FAQ:MongoDB 存储

在本页

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

存储引擎基础

什么是存储引擎?

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

另请参阅

存储引擎

是否可以在副本集中混用不同的存储引擎?

可以。您可以让副本集成员使用不同的存储引擎(比如WiredTiger和内存引擎)

注意:

从4.2版本以后,MongoDB彻底移除了废弃的MMAPv1存储引擎。

WiredTiger存储引擎

是否可以将现有的部署升级到WiredTiger引擎?

可以,请参考:

WiredTiger引擎能提供多少的压缩(比例)?

压缩数据与未压缩数据的比率取决于您的数据和所使用的压缩库。默认情况下,WiredTiger中的集合数据使用的是Snappy块压缩, 也可以使用zlibzstd压缩。索引数据默认情况下使用prefix压缩

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

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

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

  • (RAM - 1 GB)/2

  • 256 MB.

例如,在总共有4GB RAM的系统上,WiredTiger缓存将使用1.5GB RAM(0.5 *(4 GB-1 GB)= 1.5 GB)。 相反,总内存为1.25GB的系统将为WiredTiger缓存分配256MB,因为256MB大于总RAM减去1GB的一半(0.5 *(1.25 GB-1 GB)= 128 MB <256 MB)

注意:

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

关于内存限制,请参考hostInfo.system.memLimitMB

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

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

  • 文件系统缓存中的数据与磁盘上的格式相同,包括所有对数据文件进行压缩的收益。操作系统使用文件系统缓存来减少磁盘I/O。

  • 加载到WiredTiger内部缓存中的索引具有与磁盘格式不同的数据表示形式,但仍可以利用索引prefix压缩来减少RAM使用量。索引prefix压缩从索引字段中删除通用前缀。

  • WiredTiger内部缓存中的集合数据未经压缩,并使用与磁盘格式不同的表示形式。块压缩可以节省大量的磁盘存储空间,但是必须对数据进行解压缩才能由服务器端进行处理。

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

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

注意:

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

为了容纳更多的RAM使用者,您可能需要降低WiredTiger内部缓存的大小。

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

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

要查看有关缓存和淘汰率的统计信息,请参阅serverStatus命令返回的wiredTiger.cache字段的相关内容。

WiredTiger引擎多久写一次磁盘?

  • 检查点

    从3.6版开始,MongoDB将WiredTiger配置为以60秒的间隔创建检查点(即将快照数据写入磁盘)。在早期的版本中,MongoDB将在WiredTiger中以60秒的间隔或在写满2GB日志数据时对用户数据进行创建检查点操作,两个条件中任意一个满足即可。

  • 日志数据

    WiredTiger在以下任一情况满足时会将缓存的日记记录同步到磁盘:

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

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

WiredTiger引擎的可用于重用的空闲空间反映在 db.collection.stats() 的结果的wiredTiger.block-manager.file bytes availablefor reuse字段中。

为了使WiredTiger存储引擎可以将这些空闲空间归还给操作系统,可以对数据文件进行碎片整理。这可以通过compact命令实现。更多相关信息及其他考虑,请参考 compact

数据存储诊断

如何确认一个集合的大小?

要查看集合的统计信息,包括数据大小,请使用mongoshell中的db.collection.stats()方法。以下示例为在order集合上执行db.collection.stats()

db.orders.stats();

MongoDB同样提供了以下方法来返回集合的具体大小:

  • db.collection.dataSize() 会返回集合中未压缩的数据大小,以字节为单位。

  • db.collection.storageSize() 会返回集合在磁盘上占用的大小,以字节为单位。如果集合的数据是压缩过的(WiredTiger引擎默认带数据压缩),则存储大小反映的是压缩后的大小,可能会比db.collection.storageSize() 返回的结果小一些。

  • db.collection.totalIndexSize会返回集合中所有索引的大小,以字节为单位。如果一个索引使用了前缀压缩(WiredTiger引擎默认索引使用前缀压缩),则返回的大小反映的是压缩后的大小。

以下的脚本会输出每个数据库的统计信息:

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输出

译者:刘翔

校对:牟天垒