常见问题解答:自托管部署的MongoDB存储
本文档解答了关于MongoDB存储系统的一些常见问题。
存储引擎基础
什么是存储引擎?
存储引擎是数据库的一部分,负责管理数据的存储方式,包括内存和磁盘上的数据。许多数据库支持多种存储引擎,不同的引擎对特定工作负载的性能表现更优。例如,一种存储引擎可能对读密集型工作负载提供更好的性能,而另一种可能支持更高的写入吞吐量。
在副本集中可以混合使用存储引擎吗?
是的。您可以拥有使用不同存储引擎(WiredTiger和内存中)的副本集成员。
存储建议
一个集群中可以有多少个集合和索引?
当集合和索引的总数超过100,000时,集群的性能可能会下降。此外,许多大型集合对性能的影响大于小型集合。
WiredTiger 存储引擎
我能否将现有的部署升级到WiredTiger?
是的。请参阅
WiredTiger提供多少压缩比?
压缩数据与未压缩数据的比率取决于您的数据和所使用的压缩库。默认情况下,WiredTiger中的集合数据使用Snappy块压缩;也提供zlib和zstd压缩。索引数据默认使用前缀压缩。
我应该将WiredTiger内部缓存设置到多大?
使用WiredTiger,MongoDB同时利用WiredTiger内部缓存和文件系统缓存。
默认的WiredTiger内部缓存大小是以下两者中较大者
RAM的50%减去1 GB,或者
256 MB。
例如,在一个总共有4GB内存的系统上,WiredTiger缓存使用1.5GB内存(0.5 * (4 GB - 1 GB) = 1.5 GB
)。相反,在一个总共有1.25GB内存的系统上,WiredTiger分配256MB到WiredTiger缓存,因为这是总内存减去1GB后的一半以上(0.5 * (1.25 GB - 1 GB) = 128 MB < 256 MB
)。
注意
在某些情况下,例如在容器中运行时,数据库可能具有低于系统总内存的内存限制。在这种情况下,这个内存限制而不是总系统内存被用作最大可用RAM。
要查看内存限制,请参阅hostInfo.system.memLimitMB
。
默认情况下,WiredTiger对所有集合使用Snappy块压缩,对所有索引使用前缀压缩。压缩默认值可以在全局级别配置,也可以在创建集合和索引时按集合和索引设置。
在WiredTiger内部缓存与磁盘格式中,数据使用不同的表示形式。
文件系统缓存中的数据与磁盘格式相同,包括任何数据文件的压缩优势。文件系统缓存由操作系统用于减少磁盘I/O。
加载到WiredTiger内部缓存的索引具有与磁盘格式不同的数据表示形式,但仍然可以利用索引前缀压缩来减少RAM使用。索引前缀压缩从索引字段中删除常见的公共前缀。
WiredTiger内部缓存中的集合数据是不压缩的,并且与磁盘格式使用不同的表示形式。块压缩可以提供显著的磁盘存储节省,但数据必须解压缩才能由服务器处理。
使用文件系统缓存,MongoDB自动使用WiredTiger缓存或其他进程未使用的所有空闲内存。
要调整WiredTiger内部缓存的大小,请参阅storage.wiredTiger.engineConfig.cacheSizeGB
和--wiredTigerCacheSizeGB
。避免将WiredTiger内部缓存大小增加到其默认值以上。
注意
storage.wiredTiger.engineConfig.cacheSizeGB
限制了WiredTiger内部缓存的大小。操作系统使用可用空闲内存作为文件系统缓存,这允许压缩的MongoDB数据文件保留在内存中。此外,操作系统使用任何空闲RAM来缓冲文件系统块和文件系统缓存。
为了适应额外的RAM消费者,您可能需要减小WiredTiger内部缓存大小。
默认的WiredTiger内部缓存大小值假定每台机器有一个单独的mongod
实例。如果一台机器包含多个MongoDB实例,那么您应该降低设置以适应其他mongod
实例。
如果您在一个容器(例如,lxc
、cgroups
、Docker等)中运行mongod
,而这个容器无法访问系统中的全部RAM,您必须将storage.wiredTiger.engineConfig.cacheSizeGB
设置为小于容器中可用RAM的值。确切的数量取决于容器中运行的其它进程。参见memLimitMB
。
要查看缓存和驱逐率的统计信息,请查看serverStatus
命令返回的wiredTiger.cache
字段。
MongoDB为每个连接分配多少内存?
每个连接最多使用1兆字节的RAM。
为了优化连接的内存使用,请确保您
监控部署中打开的连接数量。过多的打开连接会导致RAM过度使用,并减少工作集的可用内存。
当不再需要时关闭连接池。连接池是驱动程序维护的已打开、准备就绪的数据库连接的缓存。关闭未使用的池可以释放额外的内存资源。
管理连接池的大小。连接字符串选项
maxPoolSize
指定了池中打开连接的最大数量。默认情况下,您可以在池中最多有100个打开的连接。降低maxPoolSize
会减少连接使用的最大RAM量。提示
要配置您的连接池,请参阅
Connection Pool Configuration Settings
。
WiredTiger多久写一次磁盘?
- 检查点
- MongoDB 将 WiredTiger 配置为创建检查点,具体来说,每隔 60 秒将快照数据写入磁盘。
- 日志数据
- WiredTiger 在以下任何一种情况下都会同步缓冲的日志记录到磁盘
对于副本集成员(主成员和次成员)
如果写操作包含或暗示了
j: true
的写关注。此外,对于次成员,在每次应用 oplog 条目批处理后。
注意
写关注
"majority"
如果writeConcernMajorityJournalDefault
为 true,则意味着j: true
。每 100 毫秒一次(参见
storage.journal.commitIntervalMs
)。当 WiredTiger 创建一个新的日志文件时。因为 MongoDB 使用 100 MB 的日志文件大小限制,所以 WiredTiger 大约每 100 MB 数据创建一个新的日志文件。
如何在 WiredTiger 中回收磁盘空间?
WiredTiger 存储引擎在删除文档时,会在数据文件中维护空记录的列表。此空间可以被 WiredTiger 重复使用,但除非在非常特定的情况下,否则不会返回给操作系统。
可供 WiredTiger 重复使用的空空间数量反映在 db.collection.stats()
输出的 wiredTiger.block-manager.file bytes available for reuse
标题下。
要允许 WiredTiger 存储引擎将此空空间释放给操作系统,您可以取消数据文件的碎片。这可以通过 重新同步副本集成员 或使用 compact
命令来实现。
数据存储诊断
如何检查集合的大小?
要查看集合的统计信息,包括数据大小,请在 db.collection.stats()
方法中使用mongosh
。以下示例为 orders
集合发出 db.collection.stats()
。
db.orders.stats();
MongoDB 还提供以下方法来返回集合的特定大小
db.collection.dataSize()
返回集合的未压缩数据大小(以字节为单位)。db.collection.storageSize()
返回集合在磁盘存储上的大小(以字节为单位)。如果集合数据被压缩(这是 WiredTiger 的默认设置),则存储大小反映了压缩大小,可能小于db.collection.dataSize()
返回的值。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的默认设置),则返回的索引大小反映的是压缩大小。
如何获取数据库存储使用情况的信息?
在mongosh
中的db.stats()
方法返回"活动"数据库的当前状态。有关返回字段的描述,请参阅dbStats 输出。