在1000万个MongoDB文档中查询

13

我正在将书籍元数据,例如名称、作者、价格、出版社等存储在MongoDB文档中。我有大约1000万个这些文档,并且它们都在一个集合中。 平均文档大小为1.9KB。现在我已经在名称作者价格上创建了索引。实际上,我的价格上有两个索引,一个按升序排列,一个按降序排列。我的mongodb版本是2.2.0,使用php驱动程序查询mongo。驱动程序的版本是1.12。但是,当我在价格范围内进行区间查询时,我收到了MongoCursorTimeoutException异常。在我的查询中,我试图寻找价格在某一范围内的书籍,比如“价格低于1000,高于500”。

增加超时时间似乎不是一个好主意(已经是30秒了)。除此之外还能做什么来加快查询过程呢?

编辑 实际上我的价格索引是复合索引。我有一个状态字段,它有一个整数值,因此我的价格索引看起来像{price:-1,status:1}{price:1,status:1}。 此外,我正在尝试使用PHP每次检索20个文档。


3
将价格的升序和降序索引分开是一种浪费。对于单字段索引,方向并不重要。删除其中一个索引可以释放一些索引RAM。 - JohnnyHK
@JohnnyHK 实际上我的价格指数是复合的。我有一个状态字段,它具有整数值,因此我的价格指数看起来像 {price:-1,status:1}{price:1,status:1} - lovesh
1
@lovesh 好的;即使如此,请务必使用 explain 确保这两个索引都被使用。无论如何,拥有6GB的索引和8GB的RAM感觉太紧张了。 - JohnnyHK
@JohnnyHK explain 显示了 "cursor" : "BtreeCursor price_-1_status_1",这意味着使用了复合索引,但 "isMultiKey" 的值为 false。你能告诉我原因吗? - lovesh
@lovesh isMultiKey是一个指示索引是否用于数组属性的标志,因此在这里应该为false。任何给定的查询只能使用一个索引,所以我并不是要暗示你应该检查它们是否都在这个特定的查询中使用。相反,我是想说在任何你期望索引有帮助的查询中进行检查。 - JohnnyHK
显示剩余8条评论
3个回答

5
我们在使用Mongo集合时,有着处理数百万文档的经验,使用单一/共享服务器和专用复制集,在EC2上使用传统和SSD EBS卷。工作负载各不相同:有些面向分析,而其他工作则是支持Web请求。以下是我建议的根本原因分析路径:
  1. 使用.explain()运行查询以查看索引使用情况等。如有必要,请调整索引。Mongo的优化器相当天真,如果您的索引与查询模式不完全匹配,则可能会被忽略。
  2. 检查MMS,查找以下任何问题:(1)内存中的所有数据都不是(由页面错误指示),以及(2)队列长度(通常表示某种瓶颈)。当不是所有数据都在内存中时,Mongo的性能会迅速降低,因为数据库具有单个全局锁,并且尤其在云端触摸存储是个坏消息。我们最近升级到了SSD云存储,并且在大约500 GB大小的数据库上看到了3-10倍的性能提高。
  3. 将剖析级别提高到2(最大值),运行一段时间并查看操作日志。参见MongoDB剖析器
希望这可以帮到你。

2
  1. 检查您的索引。重新索引数据,并确保在运行查询之前集合已完全索引。(10万份文档可能需要一段时间才能完成索引)
  2. 任何索引查询中最慢的部分是实际的文档检索。我可以想象,根据您要拉取的文档数量,这可能需要30秒或更长时间以及大量内存。

有关一些您可以尝试的有用说明,请查看此页面: http://www.mongodb.org/display/DOCS/Optimization

对于10万份文档,您还可以考虑将数据分片到多台计算机上。请记住,硬盘读取速度比CPU周期慢。


我正在尝试一次检索20个文档,因此“限制”为20。 - lovesh

1

正如@JohnyHK所说,我的RAM太低了。所以我将其增加到12 GB,现在它可以工作了。感谢大家的评论和答案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接