FAQ:MongoDB 存储
在本页
本文档回答了有关MongoDB存储系统的常见问题。
存储引擎基础
什么是存储引擎?
存储引擎是数据库的一部分,负责管理如何在内存和磁盘上存储数据。许多数据库支持多个存储引擎,其中不同的引擎对于特定的工作负载可能性能更好。例如,一个存储引擎可能为包含大量读取操作的工作负载提供更好的性能,而另一个引擎则可能为写入操作提供更高的吞吐量。
另请参阅
是否可以在副本集中混用不同的存储引擎?
可以。您可以让副本集成员使用不同的存储引擎(比如WiredTiger和内存引擎)
注意:
从4.2版本以后,MongoDB彻底移除了废弃的MMAPv1存储引擎。
WiredTiger存储引擎
是否可以将现有的部署升级到WiredTiger引擎?
可以,请参考:
WiredTiger引擎能提供多少的压缩(比例)?
压缩数据与未压缩数据的比率取决于您的数据和所使用的压缩库。默认情况下,WiredTiger中的集合数据使用的是Snappy块压缩, 也可以使用zlib和zstd压缩。索引数据默认情况下使用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的容器(例如lxc
,cgroups
,Docker
等)中运行 mongod
,则必须将storage.wiredTiger.engineConfig.cacheSizeGB
设置为小于该容器中可用的RAM数量。确切的数量取决于容器中运行的其他进程。请参考memLimitMB
。
要查看有关缓存和淘汰率的统计信息,请参阅serverStatus
命令返回的wiredTiger.cache
字段的相关内容。
WiredTiger引擎多久写一次磁盘?
检查点
从3.6版开始,MongoDB将WiredTiger配置为以60秒的间隔创建检查点(即将快照数据写入磁盘)。在早期的版本中,MongoDB将在WiredTiger中以60秒的间隔或在写满2GB日志数据时对用户数据进行创建检查点操作,两个条件中任意一个满足即可。
日志数据
WiredTiger在以下任一情况满足时会将缓存的日记记录同步到磁盘:
对于副本集成员(主或者从节点成员),
是否有等待oplog条目的操作。需要等待oplog条目的操作包括:
针对oplog转发扫描查询
读取操作作为因果一致性会话的一部分
另外,对于从节点成员,在每批oplog条目被应用之后。
如果写操作包括或隐含了
j: true
的写关注。注意:
当
writeConcernMajorityJournalDefault
为true
时,设置为["majority"
](https://docs.mongodb.com/v4.2/reference/write-concern/#writeconcern."majority")的写关注隐含了`j:true`。每隔100ms(参考
storage.journal.commitIntervalMs
)WiredTiger创建新的日志文件时。由于MongoDB使用的日志文件大小限制为100MB,因此WiredTiger大约每100MB数据创建一个新的日志文件。
如何在WiredTiger引擎中回收磁盘空间?
WiredTiger存储引擎在删除文档时会维护数据文件中的空记录列表。WiredTiger可以重用此空间,但是并不会将其返回给操作系统,除非是在非常特殊的情况下。
WiredTiger引擎的可用于重用的空闲空间反映在 db.collection.stats()
的结果的wiredTiger.block-manager.file bytes availablefor reuse
字段中。
为了使WiredTiger存储引擎可以将这些空闲空间归还给操作系统,可以对数据文件进行碎片整理。这可以通过compact
命令实现。更多相关信息及其他考虑,请参考 compact
。
数据存储诊断
如何确认一个集合的大小?
要查看集合的统计信息,包括数据大小,请使用mongo
shell中的db.collection.stats()
方法。以下示例为在order
集合上执行db.collection.stats()
:
MongoDB同样提供了以下方法来返回集合的具体大小:
db.collection.dataSize()
会返回集合中未压缩的数据大小,以字节为单位。db.collection.storageSize()
会返回集合在磁盘上占用的大小,以字节为单位。如果集合的数据是压缩过的(WiredTiger引擎默认带数据压缩),则存储大小反映的是压缩后的大小,可能会比db.collection.storageSize()
返回的结果小一些。db.collection.totalIndexSize
会返回集合中所有索引的大小,以字节为单位。如果一个索引使用了前缀压缩(WiredTiger引擎默认索引使用前缀压缩),则返回的大小反映的是压缩后的大小。
以下的脚本会输出每个数据库的统计信息:
以下的脚本会输出每个数据库中每个集合的统计信息:
如何确认集合中每个索引的大小?
要查看为每个索引分配的数据大小,使用 db.collection.stats()
方法,然后查看返回结果文档中的indexSizes
字段。
如果索引使用前缀压缩(这也是WiredTiger引擎的默认设置),返回的大小代表了压缩后的大小。
如何获得有关数据库存储使用的相关信息?
mongo shell中的 db.stats()
方法返回“激活”数据库的当前状态。有关返回字段的描述,请参考dbStats输出。
译者:刘翔
校对:牟天垒
最后更新于