我的机器有 42GB RAM,总索引大小为 40GB(工作集应该 100% 填充,因为索引都在 UUID 列上)。我怀疑我的工作集太大了,因为页面错误开始大幅增加,例如从平均 20 跳到 120。
我发现 mongod 似乎没有使用我所有的内存,例如
ps ax | grep mongod
23051 mongod 20 0 338g 7.7g 7.5g S 87.8 16.4 1533:17 /usr/bin/mongod -f /etc/mongod.conf
目前只使用了7.7G。
使用 2.4 的工作集估算器,我发现 50 秒内的工作集只有 650MB 左右,这似乎与我的数据大小不符。
"workingSet" : {
"note" : "thisIsAnEstimate",
"pagesInMemory" : 166069,
"computationTimeMicros" : 49281,
"overSeconds" : 50
},
你有什么主意吗?
答案1
首先,我建议您看一下这里:
https://jira.mongodb.org/browse/SERVER-9415
那期讨论的也是同样的话题。总结一下:因为MongoDB 中的日志功能以及它如何重新映射内存,这可能会导致进程的驻留内存mongod
看起来人为地低。如果您查看命令的输出free
,发现文件系统缓存相对较满,那么您更有可能遇到此驻留内存报告异常(mongod
当然,假设它是系统中唯一真正消耗大量内存的进程)。
但是,MongoDB(至少在 Linux 上)仅报告硬(实际)页面错误,而不报告软页面错误,软页面错误是指进程请求的页面已在内存中,但请求进程不“拥有”这些页面。因此,您有理由担心页面错误的增加,这是表明您的数据目前无法装入内存,因此必须访问磁盘的最佳测量方法之一。
在确认你想要的一切都在内存中时,你可以使用触摸命令将您想要的索引和数据加载到文件系统缓存(非驻留)中。应该注意的是,这是一个有点钝的工具,因为它只会将整个数据集和/或整个索引加载到缓存中,并且可能会导致系统加载/锁定 - 请谨慎使用。根据您的数据集,使用 find 查询和 explain 加载最近或已知的热数据可能会更有效。像这样:
db.collection.find({criteria for loading data}).explain()
或者,为了确保加载特定索引,请添加明确的提示:
db.collection.find({criteria for loading data}).hint({index name})explain()
另外要考虑的是,当您确实访问磁盘时,将数据加载到内存中的效率。一般来说,这是 IO 和内存利用率之间的权衡,但如果您的首要任务是内存效率,并且您有一些多余的 IO 可以用于解决问题,那么在 MongoDB 上,您通常需要调整您的预读使用设置blockdev
命令。有关更多信息,请参阅其他 Serverfault 问题/答案这里和这里。