OPTIONS
翻译或纠错本页面

FAQ: MongoDB存储

这篇文档讲述了与MongoDB存储系统有关的常见问题。

假如你没有发现你想要的答案,可以看一下这个页面 complete list of FAQs 或者把你问题发布到 MongoDB User Mailing List <https://groups.google.com/forum/?fromgroups#!forum/mongodb-user>

内存映射文件是什么?

内存映射文件中通过系统调用 mmap() 映射操作系统在内存中存放的数据,因此 maps 文件映射了部分虚拟内存。内存映射文件是MongoDB存储引擎中非常重要的一部分。通过使用内存映射文件,数据文件中的信息对MongoDB来说就像在内存中一样。这样MongoDB就可以非常快的连接和操作数据库了。

内存映射文件是如何工作的?

内存映射会将文件以字节的形式之间分配到虚拟内存。一旦产生映射,MongoDB会通过文件与内存之间的关联与之进行交互,因为文件就像在内存里一样。

MongoDB与内存映射文件是如何工作的?

MongoDB使用内存映射文件来管理数据并与之进行交互。MongoDB会使内存与数据文件进行关联,就像连接文档。数据也会映射到内存中。

什么是缺页中断?

缺页中断会导致MongoDB不在当前的物理内存进行读写操作。然而,操作系统页面错误是因为物理内存被耗尽或超出磁盘空间。

如果有闲置内存,操作系统将会在磁盘上找到该页面并直接将其加载到内存里。当然,如果没有闲置内存,操作系统将会:

  • 在内存中找到时效的和很久没有使用的页面,将其写入磁盘。

  • 从磁盘中读取请求页面并加载到内存中。

在这个过程中,特别是处于活动状态的系统,需要很长时间。可以比较一下读取已经在内存中的页面。

通过 Page Faults 查看更多信息。

软硬缺页中断有什么不同?

缺页中断 会导致MongoDB在需要连接数据时不在当前活动的内存中工作。当MongoDB需要通过磁盘连接数据时,页面”硬”错误代表当前的状态。

通过 Page Faults 查看更多信息。

在MongoDB中我可以使用什么工具来检测存储的使用情况?

mongo 命令行程序中的 db.stats() 就可以返回 “活跃”数据库现在的状态。 dbStats command 文档解释了 db.stats() 输出的字段。

什么是工作复制集?

工作复制集代表应用在正常操作进程中使用的所有数据。大部分情况下它是所有数据大小的子集,但特殊情况下工作复制集的大小取决于当前正在使用的数据库。

如果你想让MongoDB扫描集合中的所有文档,工作集将会扩展至每一个文档。基于物理内存的大小,这个可能会导致文档在工作集中 “溢出,” 或者被操作系统从物理内存中移除。当下次MongoDB需要连接这些文档时,MongoDB可能会引发一个硬缺页中断。

如果你想让MongoDB扫描集合中的所有 document, 工作集的内存中会含有所有活动的文档。

多数 active 配置在RAM中会得到更好的性能。

为什么目录里面的文件比我的数据库还要大?

默认存储目录 /data/db 中的数据文件可能会比数据库中的数据大,思考一下下面可能的原因:

  • 预配置数据文件

    在数据目录中,MongoDB预配置数据文件为一个指定的大小,这是保护文件系统碎片的一部分。MongoDB将第一个数据文件命名为 <databasename>.0,第二个为 ``<databasename>.1``等等。第一个文件 mongod 分配了64MB,第二个128MB等等,直到2GB,随后的文件都将是2GB。数据文件包括文件的分配空间但里面没有数据。 mongod 可能会出现1G分配空间中90%未使用的情况。对于大部分大数据库来说,不对数据库使用分配空间没什么大的差别。

    在类Unix系统中, mongod 预先配置了一个另外的数据文件并将磁盘空间初始化为0。当创建一个新的数据库时,预配置文件对于避免延迟有非常大的作用。

    你可以通过 preallocDataFiles 设置将预配置设为 false。但是千万不要设置 preallocDataFiles ,只需使用 preallocDataFiles 调试你经常删除的小数据库。

    在Linux系统上,当你使用 hdparm 就会知道配置是多么重要了:

    time hdparm --fallocate $((1024*1024)) testfile
    
  • oplog

    如果 mongod 是复制集成员,数据目录包括 local 数据库中 固定集合oplog.rs 文件。在64位安装包中,默认分配空间大约为磁盘空间的5%,通过 <replica-set-oplog-sizing>` 查看更多信息。在大部分实例中,你不需要调整oplog的大小。当然,如果你想调整,可以查看 修改Oplog大小

  • journal

    数据目录含有journal文件,它将MongoDB在操作数据库中的写入操作存储在磁盘上。查看 Journaling Mechanics

  • 空记录。

    当删除文档和集合时,MongoDB将会继续列出数据文件中的空记录。MongoDB可以重复使用这部分空间,但是不会释放这部分空间给操作系统。

    使用 compact`可以重组分配存储空间。通过重置存储,MongoDB可以有效的利用分配空间。 :dbcommand:`compact 需要额外2GB磁盘空间来运行。如果磁盘空间较少,禁止使用 compact

    重要

    compact only removes fragmentation from MongoDB data files and does not return any disk space to the operating system.

    使用 repairDatabase 重置存储来重建数据库可以再次利用删除的空间。 repairDatabase 需要至少2G额外磁盘空间来运行。如果磁盘空间较少,禁止使用 repairDatabase

    警告

    当使用 repairDatabase 进行修复时,需要足够的磁盘空间来支持新旧数据库。可以使用 repairDatabase 锁定其它操作,可能需要一定的时间。

如何查看集合的大小?

如果想查看集合的大小或其它信息,可以在 mongo 命令行中使用 db.collection.stats() 。如下面的例子,在 orders 集合中使用 db.collection.stats()

db.orders.stats();

通过指定方式查看数据大小,可以使用一下方法:

当然,下面的脚本可以统计每个数据库和集合:

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

我将如何查看索引的大小

如果想查看索引的数据分配大小,可以在 mongo 命令行中参照下面的步骤:

例子

Issue the following command to retrieve index namespaces:

db.system.namespaces.find()

该命令会返回一个类似下面的列表:

{"name" : "test.orders"}
{"name" : "test.system.indexes"}
{"name" : "test.orders.$_id_"}

参照下面的操作顺序查看 orders.$_id_ 索引的数据分配大小:

use test
db.orders.$_id_.stats().indexSizes

我将如何知道服务器在运行中磁盘没有空间了?

如果你的服务器中的数据文件在运行中超出磁盘空间,你将会看到类似下面的日志:

Thu Aug 11 13:06:09 [FileAllocator] allocating new data file dbms/test.13, filling with zeroes...
Thu Aug 11 13:06:09 [FileAllocator] error failed to allocate new file: dbms/test.13 size: 2146435072 errno:28 No space left on device
Thu Aug 11 13:06:09 [FileAllocator]     will try again in 10 seconds
Thu Aug 11 13:06:19 [FileAllocator] allocating new data file dbms/test.13, filling with zeroes...
Thu Aug 11 13:06:19 [FileAllocator] error failed to allocate new file: dbms/test.13 size: 2146435072 errno:28 No space left on device
Thu Aug 11 13:06:19 [FileAllocator]     will try again in 10 seconds

服务器会一直保持这种状态,锁定所有写入和删除操作。当然,读取还是可以的。如果你想删除一些数据和压缩数据,可以在重启服务器后使用 compact 命令。

如果journal文件在你的服务运行过程中超出磁盘空间,服务进程将会结束。 mongod 默认在:setting:~storage.dbPath 目录中创建journal文件。你可以使用资源管理器或symlink将其移动到其它磁盘。

注解

如果你将journal文件放置在一个外置存储器中,你将无法使用snapshot tool获得你的数据文件和journal文件。