2013-03-07 27 views
1

我注意到一个奇怪的行为。它可能是mongoid或mongodb,我不确定,但计数文档比读取文档慢。下面是我开的疑问:Mongoid:为什么提取计数比提取文档慢

Institution.all.any_of(:portaled_at.ne => nil).any_of(portaled: true).order_by(:portaled_at.desc).count 
# mongodb query and timing as per mongoid logs, 
# times are consistent over multiple runs 
# MONGODB (236ms) db['$cmd'].find({"count"=>"institutions", "query"=>{"$or"=>[{:portaled_at=>{"$ne"=>nil}}, {:portaled=>true}]}, "fields"=>nil}).limit(-1) 
# MONGODB (245ms) db['$cmd'].find({"count"=>"institutions", "query"=>{"$or"=>[{:portaled_at=>{"$ne"=>nil}}, {:portaled=>true}]}, "fields"=>nil}).limit(-1) 

Institution.all.any_of(:portaled_at.ne => nil).any_of(portaled: true).order_by(:portaled_at.desc).to_a 
# mongodb query and timing as per mongoid logs 
# times are not so consistent over multiple runs, 
# but consistently much lower than count query 
# MONGODB (9ms) db['institutions'].find({"$or"=>[{:portaled_at=>{"$ne"=>nil}}, {:portaled=>true}]}).sort([[:portaled_at, :desc]]) 
# MONGODB (18ms) db['institutions'].find({"$or"=>[{:portaled_at=>{"$ne"=>nil}}, {:portaled=>true}]}).sort([[:portaled_at, :desc]]) 

我相信索引不是$and$or查询使用MongoDB的,但即使这样,如果它很重要,我必须按降序排列上portaled_at稀疏索引。大约20万份文档中只有大约50-60份已经设置了portaled_at。

  • 轨3.2.12
  • mongoid 2.6.0
  • 的MongoDB 2.2.3

这是对我的常识,如果任何人都可以解释什么是在我打算将不胜感激。

+3

一个是运行数据库命令http://docs.mongodb.org/manual/reference/commands/,另一个是查询。有一个记录的问题(将在2.4中修复)针对非常缓慢的“count”调用。 https://jira.mongodb.org/browse/SERVER-1752 – WiredPrairie 2013-03-07 02:34:58

+0

感谢您的信息。如果你把它作为答案发布,我会很乐意接受它。 – rubish 2013-03-07 06:57:25

回答

4

虽然两者都在MongoDB中运行不同的子系统(一个使用runCommand,另一个使用标准查询引擎),但这种情况下的特定问题很可能是当前版本的MongoDb中的一个已知问题。

快速总结是,由于MongoDb正在做很多额外的工作,往往是没有必要的,因为没有提取计数是极其slow。它已经在开发分支中得到了修复,所以它在发布时应该在2.4。

0

由于某些原因,Mongo默认不使用索引来计数记录。但是,如果您正确构建查询,Mongo将从索引中计数。诀窍是只获取索引中的字段,并且必须指定查询。

在蒙戈壳牌:

db.MyCollection.find({"_id":{$ne:''}},{"_id":1}).count()

你可以通过解释方法来检查:

db.MyCollection.find({"_id":{$ne:''}},{"_id":1}).explain()

,其中将包括在输出"indexOnly" : true

而且类似的命令可以通过轻便摩托车驾驶员直接像这样被执行:

Mongoid::Sessions.default.command(:count => "MyCollection", :query=>{"_id"=>{"$ne"=>""}}, :fields => {:_id=>1})

,在我的基准(在我的实时数据,情况因人而异)大约是100倍比简单地做MyMongoidDocumentClass.count

不幸的是,似乎没有办法通过Mongoid gem快速做到这一点。