常见问题解答:自托管部署的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 输出。