2

通过 启动 Mongo 后,我运行了一个耗时300mongod的 Mongo 查询。调用我的“管理员”数据库显示 Mongo 具有1 GB 的常驻内存。文档解释说,“常驻”内存是 Mongo 使用的物理磁盘/RAM 的数量。db.serverStatus()

然后,我重新运行了相同的查询,但花了8秒。这次看resident内存,看到了5GB。

我相信,RAM 的大幅增加有助于解释为什么查询时间从 300 秒缩短到 8 秒,但为什么常驻内存跳跃得如此之快?

是否有推荐使用某种类型的“预热”步骤来准备 Mongo 以避免 300 秒的查询?

4

1 回答 1

4

MongoDB 使用操作系统的 mmap 功能是有原因的。这意味着,至少在 Linux 系统上,mongodb 的内存处理是基于操作系统的某些功能,称为内存映射文件。Linux 系统中的内存在多个级别上进行寻址,基本上任何程序都会在 32 位系统上看到总共 2GB 的地址空间,在 64 位系统上看到 128TB 的地址空间。这是一个虚拟地址空间,这意味着在 32/64 位上,可以使用 4kb 内存页来寻址大量内存(页是内存中单独处理的部分)。这就是为什么如果您在 32 位系统上启动 mongoDB 会发出警告,即此类系统上的数据库只能处理 2GB 的数据。显然,这个虚拟地址空间大于物理内存的数量,因此这些虚拟地址和物理地址之间存在映射。一些虚拟地址驻留在真正的物理内存中,因此它们位于实际内存中,但确保这一点的算法在内核方面。在 Linux 系统上运行的程序只能处理虚拟地址,如果尝试访问不在物理内存中的虚拟内存地址,则会发生页面错误(您可以在 serverStatus 命令的额外信息字段中跟踪这一点)。(你可以找到这个的简短解释 如果尝试访问不在物理内存中的虚拟内存地址,则会发生页面错误(您可以在 serverStatus 命令的额外信息字段中跟踪这一点)。(你可以找到这个的简短解释 如果尝试访问不在物理内存中的虚拟内存地址,则会发生页面错误(您可以在 serverStatus 命令的额外信息字段中跟踪这一点)。(你可以找到这个的简短解释在这里

如果虚拟地址驻留在物理内存中,则访问内存与内存一样快,访问当前没有物理地址的虚拟地址意味着从磁盘分页到内存并读取内存与磁盘随机读取一样快。(这使您的情况有所不同)

mongoDB 中有一个命令可以强制缓存集合或索引,这个命令就是touch 如果你在第一次查询之前使用这个命令将数据加载到内存中,你将在第一次尝试时在 8 秒内得到结果。不幸的是,您不能真正强制操作系统将其始终保存在内存中,因此如果您有其他事情用完内存,操作系统将在一段时间内将这些数据分页。

如果您有足够的物理内存,mongoDB 会将所有数据和索引保存在内存中。这并不总是需要的。有一部分数据需要在内存中以避免大量的页面错误,这是工作集。您可以使用db.runCommand( { serverStatus: 1, workingSet: 1 } )命令检查工作集的大小。

您无法在操作系统级别处理分页,但如果您有足够的内存,内核通常喜欢尽可能多地缓存内容。如果工作集适合内存,那么您或多或少都可以。如果某些文档真的很少被访问并且没有足够的内存来保存所有内容,那么无论如何它们都会被分页。

当您运行查询时,可能会发生几件事。索引可以覆盖,这意味着根本不会触及任何文档,如果您的查询在某些概念上是选择性的,则只会触及索引的一部分。不幸的是,很难定义内存是否足够,您唯一能做的就是监控(工作集指标是一个估计值)。内存不足的症状可以通过查看此演示文稿来识别。并使用彩信

于 2013-10-12T12:49:32.960 回答