2013-03-07 59 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快速做到這一點。