C#でMongoDB Aggregation Frameworkを使用すると、パフォーマンスの問題が発生します。Mongoシェルを介して高速に動作する集計は、C#で実行すると永遠にかかります。
C#を介してフレームワークを呼び出そうとする前に、Mongoシェルを介して次の集計を実行し、すべてが機能することを確認しました。
db.runCommand(
{
aggregate: "actions",
pipeline :
[
{ $match : { CustomerAppId : "f5357224-b1a8-4f1a-8ea2-a06a00ca597a", ActionName : "install"}},
{ $group : { _id : { CustomerAppId:"$CustomerAppId",ActionDate:"$ActionDate" }, count : { $sum : 1 } }}
]
});
スクリプトは500ミリ秒未満で実行され、予想される約200の結果を返します(CustomerAppIdはデータベース内の文字列として定義されています。集約フレームワークでGUIDを使用することはできません)。
次に、同じスクリプトをC#に移植しました。
var pipeline = new BsonArray
{
new BsonDocument
{
{
"$match",
new BsonDocument
{
{"CustomerAppId", "f5357224-b1a8-4f1a-8ea2-a06a00ca597a"},
{"ActionName", "install"}
}
},
{ "$group",
new BsonDocument
{
{ "_id", new BsonDocument
{
{
"CustomerAppId","$CustomerAppId"
},
{
"ActionName","$ActionName"
}
}
},
{
"Count", new BsonDocument
{
{
"$sum", 1
}
}
}
}
}
}
};
var command = new CommandDocument
{
{ "aggregate", "actions" },
{ "pipeline", pipeline }
};
(C#で集計を記述する簡単な方法があるかどうか教えてください:))
私はこのように実行しています:
var result = db.RunCommand(command);
問題は、サーバーを強制終了することです。CPUとメモリの使用量が大幅に増加します。db.currentOp()を確認すると、集約操作を確認できますが、最終的にはdb.killOp(1281546)を使用してそれを強制終了する必要があります。
"opid" : 1281546,
"active" : true,
"secs_running" : 294,
"op" : "query",
"ns" : "database.actions",
"query" : {
"aggregate" : "actions",
"pipeline" : [
{
"$match" : {
"CustomerAppId" : "f5357224-b1a8-4f1a-8ea2-a06a00ca597a",
"ActionName" : "install"
},
"$group" : {
"_id" : {
"CustomerAppId" : "$CustomerAppId",
"ActionName" : "$ActionName"
},
"Count" : {
"$sum" : 1
}
}
}
]
},
私には、操作は完全に正常に見え、mongoシェルから直接実行するスクリプトに似ています。C#を介して集計を実行すると、MongoDBがインデックスを見逃し、コレクション内の約600万のドキュメントすべてに対してテーブルスキャンを実行しているように感じます。
何か案は?
更新:ログ
cirrusの提案のおかげで、詳細ログを有効にしてから、tailを使用してクエリを取得しました。そして、それらは異なります!だから私は私のC#ポートに何か問題があると思います。クエリを正しくフォーマットする方法について何かアイデアはありますか?
シェルを介して実行されたときのクエリ:
Mon Oct 8 15:00:13 [conn1] run command database.$cmd { aggregate: "actions", pipeline: [ { $match: { CustomerAppId: "f5357224-b1a8-4f1a-8ea2-a06a00ca597a", ActionName: "install" } }, { $group: { _id: { CustomerAppId: "$CustomerAppId", ActionDate: "$ActionDate" }, count: { $sum: 1.0 } } } ] }
Mon Oct 8 15:00:13 [conn1] command database.$cmd command: { aggregate: "actions", pipeline: [ { $match: { CustomerAppId: "f5357224-b1a8-4f1a-8ea2-a06a00ca597a", ActionName: "install" } }, { $group: { _id: { CustomerAppId: "$CustomerAppId", ActionDate: "$ActionDate" }, count: { $sum: 1.0 } } } ] } ntoreturn:1 keyUpdates:0 locks(micros) r:27944 reslen:12705 29ms
そして、C#を介して実行されたときのクエリ:
Mon Oct 8 15:00:16 [conn8] run command database.$cmd { aggregate: "actions", pipeline: [ { $match: { CustomerAppId: "f5357224-b1a8-4f1a-8ea2-a06a00ca597a", ActionName: "install" }, $group: { _id: { CustomerAppId: "$CustomerAppId", ActionDate: "$ActionDate" }, Count: { $sum: 1 } } } ] }
2行目が欠落しているのは、クエリが終了していないためだと思います。
比較しやすいように、ここでもログを示します。スクリプトはアップ、C#はダウン:
Mon Oct 8 15:00:13 [conn1] run command database.$cmd { aggregate: "actions", pipeline: [ { $match: { CustomerAppId: "f5357224-b1a8-4f1a-8ea2-a06a00ca597a", ActionName: "install" } }, { $group: { _id: { CustomerAppId: "$CustomerAppId", ActionDate: "$ActionDate" }, count: { $sum: 1.0 } } } ] }
Mon Oct 8 15:00:16 [conn8] run command database.$cmd { aggregate: "actions", pipeline: [ { $match: { CustomerAppId: "f5357224-b1a8-4f1a-8ea2-a06a00ca597a", ActionName: "install" }, $group: { _id: { CustomerAppId: "$CustomerAppId", ActionDate: "$ActionDate" }, Count: { $sum: 1 } } } ] }