MongoDB - 重新启动服务器后不同的查询执行时间

Posted

技术标签:

【中文标题】MongoDB - 重新启动服务器后不同的查询执行时间【英文标题】:MongoDB - Different query execution times after restarting server 【发布时间】:2015-11-16 18:52:01 【问题描述】:

假设我启动了一个 mongo db 服务器:

mongo --dbpath=/some/path --port=12345 --storageEngine wiredTiger

然后我运行相同的查询 10 次(忽略第一个,以便它们都在热缓存上),如下所示:

mongo query1.js

我得到的时间是(通过time 和 mongodb 记录器验证):

8137ms 8145ms 8193ms 8091ms 8152ms 8110ms 8182ms 8142ms 8133ms 8098ms

太棒了——相当一致。所有这些都在大约 100 毫秒内,这是有道理的。

然后我以任何以下方式关闭服务器:

pkill mongod mongod --dbpath=/some/path --shutdown mongo shutdown.js

其中shutdown.js 包含:

db.getSiblingDB('admin').shutdownServer();

然后我重新启动它,使用完全相同的命令,我得到以下时间:

8531ms 8492ms 8613ms 8555ms 8538ms 8512ms 8551ms 8511ms 8608ms 8522ms

同样,它们始终在约 100 毫秒内,但它们都处于不同的基线

如果我再次这样做,它可能会在 8.38.68.9 或介于两者之间的任何位置。没有其他用户进程处于打开状态(除了那些需要 ssh 进入机器的用户进程)。

我做了如下实验:

while True: run the query 25 times and record the minimum such runtime shutdown the server and restart it, wait for it to listen

这在周末运行了两天,而我没有与机器交互,收集了 223 个数据点,最小运行时间范围从 7.9s8.9s。如果我没有在这期间关闭服务器,这不会发生,但同样,我可能会得到7.9s 的基线,或者我可能会得到8.9s 之一。

一个数据点的标准偏差(25 个查询的运行时间)总是非常低(大约 0.06),但在所有查询之间,却非常高。

是否有人对为什么会发生这种情况以及如何防止这种情况有直觉?我试图弄清楚一个查询是否比另一个查询快,但我无法获得一个好的基准来测试。重新启动服务器不是绝对必要的,但它会让我的生活更轻松,因为我并不总是让服务器运行。

【问题讨论】:

这些查询都应该作为慢查询日志的一部分记录在 mongod 日志文件中。您能否确认每批是否使用相同的索引? 这个特定的查询是一个聚合,它只做一个 $group 然后对其进行排序,所以根本不使用索引(它必须做一个 COLLSCAN)。我不确定这是否会产生任何影响。顺便说一句,我通过 Valgrind 验证了指令和缓存未命中的数量。我在指令计数(0.5%)和可忽略的缓存更改上得到了大约 0.005% 的差异,其中查询时间可以变化多达 6%,即使它们在服务器的一次启动内仅变化大约 1%。这很奇怪。 您是否正在启动 mongod 禁用 numactl? mongod、操作系统、文件系统等的确切版本是什么? 不,我没有禁用 numactl。 mongoDB 的版本是来自 Github(由我编译)在 Ubuntu 14.04 上使用 scons -j4 --use-system-tcmalloc mongod 构建的 3.0.7。数据在 ext4 文件系统上,mongodb 二进制文件在 nfs 文件服务器上。我确实收到/sys/kernel/mm/transparent_hugepage_defrag 设置为always 的警告。 mogo db 在哪个操作系统上运行? 【参考方案1】:

MongoDB 使用缓存来为您提供一些查询服务。重新启动服务器时,必须清除一些缓存。 MongoDB 将所有最近使用的数据保存在 RAM 中。如果您为查询创建了索引并且您的工作数据集适合 RAM,则 MongoDB 从内存中提供所有查询。

查询计划保存在缓存中,在 mongo 重新启动时会清除。因此,第一次运行查询需要时间。请参阅说明(“执行统计”)。

通过 WiredTiger,MongoDB 使用文件系统缓存和 WiredTiger 缓存。默认情况下,从 MongoDB 3.2 开始,WiredTiger 缓存将使用 60% 的 RAM 减去 1 GB 或使用 1 GB,以较大者为准。对于具有高达 10 GB RAM 的系统,这小于或等于 3.0 设置。对于 RAM 超过 10 GB 的系统,配置大于 3.0 设置。

在 MongoDB 3.0 中,WiredTiger 缓存默认使用 1 GB 或已安装物理 RAM 的一半,以较大者为准。

MongoDB 还通过文件系统缓存自动使用机器上的所有空闲内存(文件系统缓存中的数据被压缩)。

查看MongoDB Fundamentals

【讨论】:

如果缓存是问题所在,难道不应该在运行几次查询以预热缓存后最终解决这个问题吗?此外,整个数据库两次都适合内存(大约是 RAM 的 30%),因此有足够的空间用于缓存。 你有答案吗?【参考方案2】:

MongoDB 将当前处理数据保存在 RAM 中,因此您的查询请求在同一请求中可能需要不同的时间。 This link 会帮助你。

【讨论】:

以上是关于MongoDB - 重新启动服务器后不同的查询执行时间的主要内容,如果未能解决你的问题,请参考以下文章

mongoDB 学习三

如何在Cloud 9上重新启动MongoDB服务器并关闭终端

在 Docker 上运行的 Mongodb 正在重新启动后擦除集合

解决安装mongodb时,出现服务名无效问题。

MongoDB 连接

MongoDB 连接