1

我注意到一个奇怪的行为。它可能是 mongoid 或 mongodb,我不确定,但计数文档比获取文档慢。以下是我发出的查询:

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]])

我相信 mongodb 不会将索引用于$and$or查询,但如果重要的话,我有一个portaled_at按降序排列的稀疏索引。在大约 200,000 个文档中,只有大约 50-60 个设置了 portaled_at。

  • 导轨 3.2.12
  • mongoid 2.6.0
  • MongoDB 2.2.3

这违反了我的常识,如果有人能解释发生了什么,我将不胜感激。

4

2 回答 2

4

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

快速总结是,没有获取的计数非常,因为 MongoDb 正在做很多通常不必要的额外工作。已经在开发分支中修复了,所以发布的时候应该是2.4。

于 2013-03-07T11:47:53.870 回答
0

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

在 Mongo Shell 中:

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})

其中,在我的基准测试中(在我的实时数据上,YMMV)比简单地快 100 倍MyMongoidDocumentClass.count

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

于 2014-01-08T00:22:47.827 回答