我有一个单实例 mongodb,其中包含 3 个字段的集合:_id、block_id、payload。
- 有效载荷始终是 4096 字节二进制文件
- _id 是一个不断增加的唯一整数
该集合上有一个二级索引:
{ "v" : 1, "key" : { "block_id" : 1, "_id" : -1 },
"ns" : "testdb.testdev", "name" : "_block_id_id" }
我正在进行许多查询,例如:
query: { query: { block_id: 868413 }, orderby: { _id: -1 } } ntoreturn:1 nscanned:1 nreturned:1 reslen:4166 163ms
在此期间没有其他查询。当我按 block_id 顺序读取时,它比使用随机 block_id 查询快 10 倍。我的 CPU 使用率很低,存储利用率也很低。集合比内存大小大 2-3 倍。
这里的瓶颈可能是什么?
答案1
这里有几件事需要澄清:
- 您只会看到默认记录的慢速查询(> 100 毫秒),您可能会有数百万个查询在该阈值下执行,但这些查询永远不会被记录
- 找出操作缓慢的原因的方法是查看记录缓慢操作时的统计数据
- 您应该使用以下方法重新运行查询。解释()确保他们正在使用你认为的索引
就统计数据而言,有两种基本方法可以获取它们。第一种也是最快的方法是蒙哥斯塔特和蒙哥马利。这两个实用程序随 MongoDB 一起提供,可用于查明数据库正在做什么。
另一个选择是彩信(MongoDB 监控服务) - 它是免费的,它可以让您绘制随时间变化的所有相关统计数据,这样您就可以在看到速度缓慢时确定什么是峰值/下降。如果您选择这种方式,我建议您安装 munin-node(请参阅 MMS 文档),因为它可以让您查看 IO 统计数据以及 MongoDB 统计数据。
您通常会寻找下列内容之一:
- 页面错误 - 如果出现峰值,则您的查询会导致分页到磁盘 - 这比内存操作慢一个数量级,需要最小化。
- 常驻内存 - 与页面错误密切相关,这表示内存中的工作集。您提到您的数据集是 RAM 大小的 2-3 倍,但您是否在该估算中包含了索引(请参阅db.collection.stats()命令)
还有许多其他事情需要查看,但根据您的描述,这是一个很好的开始。请记住,如果您有内存争用,则越新的东西就越有可能已经在内存中。由于您使用的是顺序 ID,我预计较旧的 ID(除非最近更新或触及)会比新 ID 更频繁地出现在慢速查询日志中(这是操作系统通常管理内存的方式 - 请参阅最小可用单元了解更多信息)。
在解决此类性能问题方面,除了添加更多 RAM 之外,还应考虑: