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.3
、8.6
、8.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.9s
到 8.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 - 重新启动服务器后不同的查询执行时间的主要内容,如果未能解决你的问题,请参考以下文章
如何在Cloud 9上重新启动MongoDB服务器并关闭终端