我在通过C#使用MongoDB聚合框架时遇到了性能问题。在C#中执行时,通过Mongo Shell快速运行的聚合需要永久性。通过C#使用MongoDB聚合框架时的性能问题
试图调用通过C#的框架之前,我通过蒙戈shell中执行下列聚合检查一切正常:
db.runCommand(
{
aggregate: "actions",
pipeline :
[
{ $match : { CustomerAppId : "f5357224-b1a8-4f1a-8ea2-a06a00ca597a", ActionName : "install"}},
{ $group : { _id : { CustomerAppId:"$CustomerAppId",ActionDate:"$ActionDate" }, count : { $sum : 1 } }}
]
});
在< 500ms的执行的脚本和返回预期的大约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 shell运行。感觉像通过C#运行聚合会导致MongoDB错过索引,并且它正在对集合中所有大约600万个文档执行表扫描。
任何想法?
更新:日志
得益于Cirrus的建议,我启用了详细日志记录,然后用尾巴来获取查询。和他们是不同的!所以我认为我的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 } } } ] }
下联丢失,我想因为查询未完成。
这里再次提供日志以方便比较。脚本到了,C#down:
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 } } } ] }
你知道你已经使用ActionDate在C#版C#LINQ提供MongoDB的聚合框架,而不是到Action版本的shell版本吧?除此之外,在配置文件中使用“verbose = true”开启日志记录,并使用tail.exe日志文件。它会显示它在数据库上执行的实际查询。 – cirrus
其实不行!我发誓我三重检查了一些事情,但我仍然设法想念它。但不幸的是执行速度仍然很慢。该索引包含ActionName,CustomerAppId和ActionDate。使用AppId&Date或AppId&ActionName从shell进行分组速度很快,但从代码来看,它们都很慢。感谢提供详细的建议。我得检查一下。 –
不要忘记你可以upvote有用的意见,以及答案; – cirrus