# FAQ: MongoDB存储

在本页面

* [存储引擎基础知识](https://docs.mongodb.com/manual/faq/storage/#storage-engine-fundamentals)
* [您可以在副本集中混用存储引擎吗？](https://docs.mongodb.com/manual/faq/storage/#can-you-mix-storage-engines-in-a-replica-set)
* [WiredTiger存储引擎](https://docs.mongodb.com/manual/faq/storage/#wiredtiger-storage-engine)
* [数据存储诊断](https://docs.mongodb.com/manual/faq/storage/#data-storage-diagnostics)

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

## 存储引擎基础知识

### 什么是存储引擎？[¶](https://docs.mongodb.com/manual/faq/storage/#what-is-a-storage-engine)

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

参见

[储存引擎](https://docs.mongodb.com/manual/core/storage-engines/)

## 您可以在副本集中混用存储引擎吗？

可以。您可以让副本集成员使用不同的存储引擎（WiredTiger和内存中）

注意

从4.2版开始，MongoDB删除不推荐使用的MMAPv1存储引擎。

## WiredTiger存储引擎

### 我可以将现有部署升级到WiredTiger吗？

可以。参见：

* [将单机部署的存储引擎更改为WiredTiger](https://docs.mongodb.com/manual/tutorial/change-standalone-wiredtiger/)
* [将副本集的存储引擎更改为WiredTiger](https://docs.mongodb.com/manual/tutorial/change-replica-set-wiredtiger/)
* [将分片集群的存储引擎更改为WiredTiger](https://docs.mongodb.com/manual/tutorial/change-sharded-cluster-wiredtiger/)

### WiredTiger提供的压缩比率是多少？

压缩数据与未压缩数据的比率取决于您的数据和使用的压缩算法库。默认情况下，WiredTiger中的集合数据使用[Snappy块压缩](https://docs.mongodb.com/manual/reference/glossary/#term-snappy)；也可以使用[zlib](https://docs.mongodb.com/manual/reference/glossary/#term-zlib) 和[zstd](https://docs.mongodb.com/manual/reference/glossary/#term-zstd)压缩。索引数据默认使用[前缀压缩](https://docs.mongodb.com/manual/reference/glossary/#term-prefix-compression)。

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

通过WiredTiger，MongoDB可以利用WiredTiger内部缓存和文件系统缓存。

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

* 50％（内存大小 -1 GB），或
* 256 MB。

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

注意

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

要查看内存限制，请参阅[`hostInfo.system.memLimitMB`](https://docs.mongodb.com/manual/reference/command/hostInfo/#hostInfo.system.memLimitMB)。

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

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

* 文件系统缓存中的数据与磁盘格式相同，包括对数据文件进行的任何压缩的好处也是一样的。操作系统使用文件系统缓存来减少磁盘I / O。
* 加载到WiredTiger内部缓存中的索引的数据表示形式与磁盘格式不同，但是仍可以利用索引前缀压缩来减少内存使用量。索引前缀压缩可从索引字段中删除通用前缀。
* WiredTiger内部缓存中的集合数据是未压缩的，并使用与磁盘格式不同的表示形式。块压缩可以节省大量的磁盘存储空间，但数据必须解压缩才能由服务器操作。

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

要调整WiredTiger内部缓存的大小，请参阅 [`storage.wiredTiger.engineConfig.cacheSizeGB`](https://docs.mongodb.com/manual/reference/configuration-options/#storage.wiredTiger.engineConfig.cacheSizeGB)和 [`--wiredTigerCacheSizeGB`](https://docs.mongodb.com/manual/reference/program/mongod/#cmdoption-mongod-wiredtigercachesizegb)。避免将WiredTiger内部缓存的大小增加到其默认值以上。

注意

[`storage.wiredTiger.engineConfig.cacheSizeGB`](https://docs.mongodb.com/manual/reference/configuration-options/#storage.wiredTiger.engineConfig.cacheSizeGB)限制WiredTiger内部缓存的大小。操作系统将使用可用的空闲内存进行文件系统缓存，从而允许压缩的MongoDB数据文件保留在内存中。此外，操作系统将使用任何可用的内存来缓冲文件系统块和文件系统缓存。

为了容纳更多的RAM使用者，您可能必须减小WiredTiger内部缓存的大小。

默认的WiredTiger内部缓存大小值假定每台计算机有一个[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)实例。如果一台机器包含多个MongoDB实例，则应减小设置以容纳其他[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod) 实例。

如果您的[`mongod`](https://docs.mongodb.com/manual/reference/program/mongod/#bin.mongod)是运行在无法访问所有系统中所有可用的内存的容器（例如`lxc`， `cgroups`，Docker，等等）中时，您必须将[`storage.wiredTiger.engineConfig.cacheSizeGB`](https://docs.mongodb.com/manual/reference/configuration-options/#storage.wiredTiger.engineConfig.cacheSizeGB)的值设置为小于容器中可用内存大小的值。确切的大小取决于容器中运行的其他进程。请参阅 [`memLimitMB`](https://docs.mongodb.com/manual/reference/command/hostInfo/#hostInfo.system.memLimitMB)。

要查看有关缓存和缓存淘汰率的统计信息，请参阅[`wiredTiger.cache`](https://docs.mongodb.com/manual/reference/command/serverStatus/#serverstatus.wiredTiger.cache)命令返回的[`serverStatus`](https://docs.mongodb.com/manual/reference/command/serverStatus/#dbcmd.serverStatus)字段。

### WiredTiger写入磁盘的频率如何？[¶](https://docs.mongodb.com/manual/faq/storage/#how-frequently-does-wiredtiger-write-to-disk)

* Checkpoints（检查点）

  从版本3.6开始，MongoDB将WiredTiger配置为以60秒的间隔创建检查点（即，将快照数据写入磁盘）。在早期版本中，MongoDB将检查点设置为在WiredTiger中以60秒的间隔或在写入2 GB的预写日志数据时，对用户数据进行检查，以先发生者为准。
* Journal Data（预写日志数据）

  WiredTiger根据以下间隔或条件写入磁盘：

  * 对于副本集成员（主节点和次节点成员），
    * 如果有等待操作日志输入的操作，可以等待操作日志条目的操作包括:
      * 针对oplog转发扫描查询
      * 读取操作，作为[因果一致会话的](https://docs.mongodb.com/manual/core/read-isolation-consistency-recency/#causal-consistency)一部分
    * 另外，对于从节点成员，在每次批量处理oplog条目之后。
  * 如果写入操作包括写关注的j参数： [`j: true`](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern.j)

    注意

    如果[`writeConcernMajorityJournalDefault`](https://docs.mongodb.com/manual/reference/replica-configuration/#rsconf.writeConcernMajorityJournalDefault)是真的，写关注\[`"majority"`]\([https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority")参数为\`j](https://docs.mongodb.com/manual/reference/write-concern/#writeconcern."majority"%29参数为`j): true\`。
* 每隔100毫秒（请参阅[`storage.journal.commitIntervalMs`](https://docs.mongodb.com/manual/reference/configuration-options/#storage.journal.commitIntervalMs)）。
* WiredTiger创建新的日记文件时。由于MongoDB使用的预写日志文件大小限制为100 MB，因此WiredTiger大约每100 MB数据创建一个新的日志文件。

### 如何在WiredTiger中回收磁盘空间？

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

WiredTiger可以重用的可用空间量反映在[`db.collection.stats()`](https://docs.mongodb.com/manual/reference/method/db.collection.stats/#db.collection.stats)标题下的`wiredTiger.block-manager.file bytes available for reuse`输出中。

为了使WiredTiger存储引擎可以将此空白空间释放给操作系统，可以对数据文件进行碎片整理。这可以使用[`compact`](https://docs.mongodb.com/manual/reference/command/compact/#dbcmd.compact)命令来实现。有关其行为和其他注意事项的更多信息，请参见[`compact`](https://docs.mongodb.com/manual/reference/command/compact/#dbcmd.compact)。

## 数据存储诊断[¶](https://docs.mongodb.com/manual/faq/storage/#data-storage-diagnostics)

### 如何查看集合的大小？

要查看集合的统计信息，包括数据大小，请使用[`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) shell程序中的[`db.collection.stats()`](https://docs.mongodb.com/manual/reference/method/db.collection.stats/#db.collection.stats)方法([https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo)。以下示例为\`orders\`集合执行\[db.collection.stats()\`\](https://docs.mongodb.com/manual/reference/method/db.collection.stats/#db.collection.stats)：](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo%29。以下示例为`orders`集合执行\[db.collection.stats%28%29`]%28https://docs.mongodb.com/manual/reference/method/db.collection.stats/#db.collection.stats%29：)

复制

```
db.orders.stats();
```

MongoDB还提供以下方法来返回集合的特定大小信息：

* [`db.collection.dataSize()`](https://docs.mongodb.com/manual/reference/method/db.collection.dataSize/#db.collection.dataSize) 返回该集合的未压缩数据大小（以字节为单位）。
* [`db.collection.storageSize()`](https://docs.mongodb.com/manual/reference/method/db.collection.storageSize/#db.collection.storageSize)返回磁盘存储上集合的大小（以字节为单位）。如果集合数据被压缩（即[`default for WiredTiger`](https://docs.mongodb.com/manual/reference/program/mongod/#cmdoption-mongod-wiredtigercollectionblockcompressor)），则存储大小将反映压缩后的大小，并且可能小于[`db.collection.dataSize()`](https://docs.mongodb.com/manual/reference/method/db.collection.dataSize/#db.collection.dataSize)所返回的值 。
* [`db.collection.totalIndexSize()`](https://docs.mongodb.com/manual/reference/method/db.collection.totalIndexSize/#db.collection.totalIndexSize)返回集合的索引大小（以字节为单位）。如果索引使用前缀压缩（即[`default for WiredTiger`](https://docs.mongodb.com/manual/reference/program/mongod/#cmdoption-mongod-wiredtigerindexprefixcompression)），则返回的大小将反映压缩后的大小。

以下脚本打印每个数据库的统计信息：

复制

```
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);
   })
})
```

### 如何检查集合的各个索引的大小？[¶](https://docs.mongodb.com/manual/faq/storage/#how-can-i-check-the-size-of-the-individual-indexes-for-a-collection)

要查看为每个索引分配的数据大小，请使用 [`db.collection.stats()`](https://docs.mongodb.com/manual/reference/method/db.collection.stats/#db.collection.stats)方法并检查返回文档中的[`indexSizes`](https://docs.mongodb.com/manual/reference/command/collStats/#collStats.indexSizes)字段。

如果索引使用前缀压缩（即[`default for WiredTiger`](https://docs.mongodb.com/manual/reference/program/mongod/#cmdoption-mongod-wiredtigerindexprefixcompression)），则该索引的返回大小将反映压缩后的大小。

### 如何获得有关数据库存储使用的信息？[¶](https://docs.mongodb.com/manual/faq/storage/#how-can-i-get-information-on-the-storage-use-of-a-database)

[`mongo`](https://docs.mongodb.com/manual/reference/program/mongo/#bin.mongo) shell中的[`db.stats()`](https://docs.mongodb.com/manual/reference/method/db.stats/#db.stats)方法返回“活跃”数据库的当前状态。有关返回的字段的说明，参见[dbStats Output](https://docs.mongodb.com/manual/reference/command/dbStats/#dbstats-output)。

原文链接：<https://docs.mongodb.com/manual/faq/storage/>

译者：钟秋

update:小芒果


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.mongoing.com/faq/mongodb-storage.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
