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 for$andおよびクエリでは使用されないと思いますが、問題がある場合は、降順で$orスパース インデックスを使用します。portaled_at約 200,000 のドキュメントのうち、portaled_at が設定されているのは約 50 ~ 60 だけです。

  • レール3.2.12
  • モンゴイド 2.6.0
  • モンゴッド 2.2.3

これは私の常識に反することであり、何が起こっているのか説明できる人がいれば、本当に感謝しています。

4

2 に答える 2

4

この 2 つは MongoDB の異なるサブシステムを介して実行されていますが (一方はrunCommandを使用し、もう一方は標準のクエリ エンジンを使用しています)、この場合の特定の問題は、MongoDb の現在のバージョンの既知の問題である可能性が非常に高くなります。

簡単にまとめると、MongoDb は多くの場合不要な余分な作業を行っているため、フェッチなしでカウントすると非常に遅くなります。これは開発ブランチで修正されているため、リリース時には 2.4 に含まれているはずです。

于 2013-03-07T11:47:53.870 に答える
0

何らかの理由で、Mongo はインデックスのみを使用してレコードをカウントしないようにデフォルト設定されています。ただし、クエリを正しく作成すると、Mongo はインデックスからカウントします。トリックは、インデックスにあるフィールドのみを取得することであり、クエリを指定する必要があります。

Mongo シェルの場合:

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

Explain メソッドで確認できます。

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

これは"indexOnly" : true出力に含まれます。

同様に、コマンドは次のように Moped ドライバーを介して直接実行できます。

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

私のベンチマーク(私のライブデータ、YMMV)では、単純に実行するよりも約100倍高速ですMyMongoidDocumentClass.count

残念ながら、Mongoid gem を使用してこれを迅速に行う方法はないようです。

于 2014-01-08T00:22:47.827 に答える