常见问题解答:适用于自管理部署的 MongoDB 存储
本文档用于解答有关 MongoDB 存储系统的常见问题。
存储引擎基础知识
什么是存储引擎?
存储引擎是数据库的一部分,它负责管理数据在内存和磁盘上的存储方式。很多数据库支持多种存储引擎,而不同的引擎可为特定工作负载提供更好的性能。例如,一种存储引擎可能会为读取密集型工作负载提供更好的性能,另一种存储引擎则可能为写入操作提供更高的吞吐量。
是否可以在副本集中混合使用存储引擎?
是的。您可以拥有使用不同存储引擎(WiredTiger 和内存型)的副本集节点。
存储建议
一个集群中可以有多少个集合和索引?
一旦集合和索引的总数超过 100,000,集群性能可能会下降。此外,大量大型集合对性能的影响要比相同数量小型集合对性能产生的影响更大。
WiredTiger 存储引擎
我是否可以将现有部署升级到 WiredTiger?
是的,可以。请参阅:
WiredTiger 提供多少压缩?
压缩率取决于数据和使用的压缩库。默认情况下,WiredTiger 中的集合数据使用 Snappy 区块压缩;zlib 和 zstd 压缩也可用。索引数据默认使用前缀压缩。
我应该将 WiredTiger 内部缓存设为多大?
借助 WiredTiger,MongoDB 可同时利用 WiredTiger 内部缓存和文件系统缓存。
默认 WiredTiger 内部缓存大小为以下两者中的较大者:
(RAM 大小 - 1 GB)的 50%,或
256 MB.
例如,在总 RAM 为 4GB 的系统上,WiredTiger 缓存使用 1.5GB RAM (0.5 * (4 GB - 1 GB) =
1.5 GB
)。相反,在总 RAM 为 1.25GB 的系统上,WiredTiger 为 WiredTiger 缓存分配了 256 MB,因为这大于总 RAM 的一半减去 1 GB (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 MB RAM。
要优化连接的内存使用,请确保:
监控部署的打开连接数。打开的连接数过多会导致 RAM 过度使用,进而减少工作集的可用内存。
当不再需要它们时,关闭连接池。连接池是由驱动程序维护的、开放且随时可用的数据库连接的缓存。关闭不需要的连接池可以释放更多内存资源。
管理连接池的大小。
maxPoolSize
连接字符串选项指定池中打开的最大连接数。默认情况下,池中最多可有 100 个打开的连接。降低maxPoolSize
会减少用于连接的最大 RAM 量。提示
要配置连接池,请参阅连接池配置设置。
WiredTiger 向磁盘写入的频率是多少?
- 检查点
- MongoDB 配置 WiredTiger 创建检查点,具体而言,就是以 60 秒的间隔将快照数据写入磁盘。
- Journal Data
- 当满足以下任一条件时,WiredTiger 会将缓冲的日志记录同步到磁盘:
对于副本集成员(主节点和从节点成员):
如果写入操作包含或暗示
j: true
的写关注。此外,对于从节点,在每次批量应用 oplog 条目之后进行。
注意
如果
writeConcernMajorityJournalDefault
为真,则写关注"majority"
暗示为
j: true
。
每 100 毫秒一次(请参阅
storage.journal.commitIntervalMs
)。当 WiredTiger 创建新的日志文件时。由于 MongoDB 使用上限 100 MB 的日志文件,所以 WiredTiger 大约每 100 MB 数据创建一份新日志文件。
如何在 WiredTiger 中回收磁盘空间?
WiredTiger 存储引擎在删除文档时会在数据文件中维护空记录列表。此空间可被 WiredTiger 重用,但不会返回给操作系统(特殊情况除外)。
可供 WiredTiger 重用的空闲空间量反映在 wiredTiger.block-manager.file bytes available for reuse
下的
db.collection.stats()
输出中。
要允许 WiredTiger 存储引擎将此空闲空间释放给操作系统,可以对数据文件进行碎片整理。这可以通过重新同步副本集节点或使用 compact
命令来实现。
数据存储诊断
如何查看集合的大小?
如要查看集合的统计信息(包括数据大小),请使用 db.collection.stats()
中的mongosh
方法。以下示例为 orders
集合发出
db.collection.stats()
:
db.orders.stats();
MongoDB 还提供以下方法返回集合的特定大小信息:
db.collection.dataSize()
可返回集合的未压缩数据大小(以字节为单位)。db.collection.storageSize()
以返回磁盘存储器上集合的大小(以字节为单位)。如果对集合数据进行压缩(即default for WiredTiger
),存储大小则会反映压缩后的大小,且可能小于db.collection.dataSize()
返回的值。db.collection.totalIndexSize()
可返回集合的索引大小(以字节为单位)。如果索引使用前缀压缩(即default for 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
字段。
如果索引使用前缀压缩(即 default for
WiredTiger
),针对该索引返回的大小将反映压缩后的大小。
如何获取数据库存储使用情况的相关信息?
mongosh
中的
db.stats()
方法会返回“活动”数据库的当前状态。有关返回字段的说明,请参阅 dbStats 输出。