MongoDB:随机与顺序读取性能

我有一个具有3个字段集合的单实例mongodb:_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毫秒)logging的查询速度慢,您可能有数百万的查询执行在该阈值,永远不会被logging
  2. 找出缓慢操作的原因是在慢速操作被logging时查看统计数据的方法
  3. 您应该使用.explain()重新运行查询,以确保它们正在使用您认为它们的索引

在统计方面,有两个基本的方法来获得它们。 首先,最快的是mongostat和mongotop 。 这两个实用程序附带MongoDB,可以用来确定你的数据库是什么。

另一种select是MMS (MongoDB监控服务) – 它是免费的,它可以让你随时间变化显示所有相关的统计数据,因此当你看到缓慢的时候,你可以确定什么是尖峰/沉降。 如果沿着这条路线走,我build议安装munin-node(请参阅MMS文档),因为它可以让您了解IO统计信息以及MongoDB统计信息。

您通常会寻找以下之一:

  1. 页面错误 – 如果这是尖峰的,你的查询导致分页到磁盘 – 这是比内存操作慢一个数量级,并且需要被最小化。
  2. 驻留内存 – 与页面错误密切相关,这代表了您在内存中的工作集。 你提到你的数据集是RAM大小的2-3倍,但是你是否在这个估计中包含了索引(请参阅db.collection.stats()命令)

还有很多其他的东西需要考虑,但是根据你的描述,这是一个好的开始。 请记住,如果你有内存争夺,那么越新的东西越有可能已经在记忆中。 由于您使用的是顺序ID,我希望较旧的ID(除非最近更新或触摸)在新的caching查询日志中显示(这是操作系统通常pipe理内存的方式 – 请参阅LRU了解更多信息)。

在处理这类性能问题方面,除了增加更多的内存之外,还应该看看:

  1. 删除可能占用空间的不需要的索引
  2. 如果可能,请查看使用覆盖的索引查询(不需要在数据中进行分页,只是索引)
  3. 检查你的预先设置 – 一个漫长而复杂的话题 – 看到这里和这里的更多信息(和更多的信息一般)