某些MongoDB查询的性能极差

时间:2012-07-26 13:17:20

标签: performance mongodb

我有一个大约30K项目的集合,所有项目都有一个名为Program的元素。 “程序”是复合索引的第一部分,因此查找具有特定程序值的项目非常快。运行范围查询也很快,例如:

db.MyCollection.find(
{ $and: [ { Program: { "$gte" : "K", "$lt" : "L" } }, 
{ Program: { "$gte" : "X", "$lt" : "Y" } } ] }).count();

上面的查询没有返回任何结果,因为我正在查询两个非重叠范​​围(K-L)和(X-Y)的重叠。左范围(K-L)包含约7K项目。

但是,如果我用“where”表达式替换第二个“and”子句,则查询执行需要很长时间:

db.MyCollection.find(
{ $and: [ { Program: { "$gte" : "K", "$lt" : "L" } }, { "$where" : "this.Program == \"Z\"" } ] }).count();

如您所见,上面的查询也应该返回一个空结果集(范围K-L与Program ==“Z”组合)。我知道“where”的性能很慢,但是Mongo不应该首先通过评估left子句来减少潜在的结果集(这将导致大约7K项),然后才应用“where”检查?如果确实如此,那么在我的机器上处理几千件物品时不应该花费几秒而不是几分钟,而Mongo服务在执行此操作时会消耗大约3GB RAM吗?对于相对较小的收藏来说看起来太重了。

1 个答案:

答案 0 :(得分:3)

你可以做一些事情 -

  1. 使用explain()查看您的查询发生了什么。 explain()被描述为here。使用$ explain运算符返回描述用于返回查询的进程和索引的文档。例如 -

    db.collection.find(查询).explain()

  2. 如果这不能返回足够的信息,您可以查看Database Profiler。但是,请记住,这不是免费的,并且本身会增加负载。在此页面中,您还可以找到有关优化查询效果的基本notes

  3. 但是,在您的情况下,这一切都归结为$ where运算符:

    $ where评估JavaScript并且无法利用索引。因此,当您使用标准MongoDB运算符(例如,$ gt,$ in)表达查询时,查询性能会提高。

    通常,只有当您无法使用其他运算符表达查询时,才应使用$ where。如果必须使用$ where,请尝试包含至少一个其他标准查询运算符以过滤结果集。单独使用$ where需要进行表扫描。 $ where,与Map Reduce一样,限制了您的concurrency

  4. 作为一个FYI:有关explain()的输出的几点注意事项:

    • ntoreturn客户端请求从查询返回的对象数。例如,findOne(),将ntoreturn设置为limit()设置适当的限制。零表示没有限制。
    • query查询规范的详细信息。
    • nscanned执行操作时扫描的对象数。
    • reslen查询结果长度,以字节为单位。
    • nreturned查询返回的对象数。