16

配列内のいくつかの値をローテーションする必要があるドキュメントに対して更新操作を実行する必要があります。現在、MongoDB 更新クエリでは、更新で同じフィールドに対して$popと を実行することはできません。$pushオンラインでアドバイスを検索した後、db.eval()原子性が保証され、実行している操作が非常に短いため、データベースが長時間ロックされないため、これが私の使用に最も適していると判断しました。

これが私がやろうとしていることの例です:

db.eval(function (id, newVal) {
    doc = db.collection.findOne({_id: id});
    doc.values.shift();
    doc.values.push(newVal);
    db.collection.save(doc);
}, id, newVal);

そして、これは完全に機能します!次に、mongoDB プロファイリングを有効にして、コマンドが何ミリ秒eval()かかったかを確認しました。結果は常に 1 ミリ秒未満でした。

 > db.system.profile.find({op: "command"}, {"millis": 1}) 
 { "millis" : 0 }
 { "millis" : 0 }
 ...

私のアプリケーションが python であることを除けば、これは私にとって朗報です。そのため、pymongo クライアントを使用してeval()コマンドを実行しています。(上記のデータはmongoシェルからのものです)しかし、今、eval()pymongoを使用して同じコマンドを実行すると:

conn = pymongo.Connection(mongo_server_hostname)
db = conn.my_db

db.eval("""function (id, newVal) {
    doc = db.collection.findOne({_id: id});
    doc.values.shift();
    doc.values.push(newVal);
    db.collection.save(doc);
}""", id, new_val)

非常に異なるプロファイリング結果が得られます。

> db.system.profile.find({op: "command"}, {"millis": 1}) 
{ "millis" : 13 }
{ "millis" : 14 }
{ "millis" : 14 }
...

eval()mongo シェルと pymongo 内から同じコマンドを実行すると、サーバーが pymongo から同じコマンドを実行するのに 14 ミリ秒多くかかるという根本的な違いはありますか?

4

1 に答える 1

1

表示されている不一致の考えられる原因の 1 つ (必ずしも原因であるとmongo限りません) は、シェルとmongodサーバーの両方がデフォルトでGoogle の v8 Javascript エンジンを使用することです (代わりに Spidermonkey を使用するように構成することもできます)。あなたが与える。

Google の v8 では、Javascript コードにホットスポットが見られ、頻繁に使用されるコードを JIT する可能性があります。

一方、バニラの PyMongo は純粋な Pythonで記述されているため、常に解釈されるため、かなりのオーバーヘッドが発生します。

まだ行っていない場合は、デフォルトの代わりに C で記述された PyMongo 拡張機能を使用するか、アプリケーションの残りの部分に互換性がある場合は、Python 用の PyPy JIT インタープリターを使用することが 1 つの可能性です。

Debian から派生したディストリビューション (Ubuntu など) を使用する場合、パッケージpython-pymongo-extは PyMongoの C バージョンのコンパイル済みバージョンを提供します。

于 2013-04-22T08:39:44.937 に答える