C# 通过C使用MongoDB聚合框架时的性能问题
当通过C使用MongoDB聚合框架时,我遇到了性能问题。使用C执行一个通过MongoShell快速工作的聚合需要花费很长时间 在尝试通过C调用框架之前,我通过Mongo shell执行了以下聚合,以检查一切是否正常:C# 通过C使用MongoDB聚合框架时的性能问题,c#,mongodb,mongodb-.net-driver,C#,Mongodb,Mongodb .net Driver,当通过C使用MongoDB聚合框架时,我遇到了性能问题。使用C执行一个通过MongoShell快速工作的聚合需要花费很长时间 在尝试通过C调用框架之前,我通过Mongo shell执行了以下聚合,以检查一切是否正常: db.runCommand( { aggregate: "actions", pipeline : [ { $match : { CustomerAppId : "f5357224-b1a8-4f1
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和mem的使用率会大幅上升。当我检查db.currentOp时,我可以看到聚合操作,但我最终不得不使用db.killOp1281546终止它:
"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
}
}
}
]
},
对我来说,这个操作看起来非常好,与我直接从MongoShell运行的脚本类似。感觉上,通过C运行聚合会导致MongoDB丢失索引,并对集合中的所有~600万个文档进行表扫描
有什么想法吗
更新:日志
多亏了cirrus的建议,我启用了详细日志记录,然后使用tail获取查询。他们是不同的!所以我认为我的C端口有问题。有没有关于如何正确设置查询格式的想法
通过shell执行查询时:
以及通过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向下:
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 } } } ] }
结果是我对管道对象的格式设置不正确。$match和$group都必须位于各自的BsonDocument实例中。以下代码似乎产生了正确的输出:
var pipeline = new BsonArray
{
new BsonDocument
{
{
"$match",
new BsonDocument
{
{"CustomerAppId", "f5357224-b1a8-4f1a-8ea2-a06a00ca597a"},
{"ActionName", "install"}
}
}
},
new BsonDocument
{
{ "$group",
new BsonDocument
{
{ "_id", new BsonDocument
{
{
"CustomerAppId","$CustomerAppId"
},
{
"ActionDate","$ActionDate"
}
}
},
{
"Count", new BsonDocument
{
{
"$sum", 1
}
}
}
}
}
}
};
我真的希望管道中有一个用于MongoDB聚合框架的C Linq提供程序:结果是我对管道对象的格式设置不正确。$match和$group都必须位于各自的BsonDocument实例中。以下代码似乎产生了正确的输出:
var pipeline = new BsonArray
{
new BsonDocument
{
{
"$match",
new BsonDocument
{
{"CustomerAppId", "f5357224-b1a8-4f1a-8ea2-a06a00ca597a"},
{"ActionName", "install"}
}
}
},
new BsonDocument
{
{ "$group",
new BsonDocument
{
{ "_id", new BsonDocument
{
{
"CustomerAppId","$CustomerAppId"
},
{
"ActionDate","$ActionDate"
}
}
},
{
"Count", new BsonDocument
{
{
"$sum", 1
}
}
}
}
}
}
};
我真的希望MongoDB聚合框架中有一个C Linq提供者:你知道你在C版本中使用了ActionDate,而不是在shell版本中使用ActionName,对吗?除此之外,在配置文件中使用verbose=true打开日志记录,并在日志文件中使用tail.exe。它将向您显示它在数据库上执行的实际查询。实际上不是!我发誓我已经检查了三次了,但我还是错过了。但不幸的是,执行仍然缓慢。索引包含ActionName、CustomerAppId和ActionDate。使用AppId&Date或AppId&ActionName从shell进行分组速度很快,但从代码来看,两者都很慢。谢谢你的详细提示。我得查一查。别忘了你可以上传有用的评论和答案;使用Mongo 2.4,我可以将聚合框架与二进制表示的GUI结合使用。您知道,您在C版本中使用了ActionDate,而在shell版本中使用了ActionName,对吗?除此之外,在配置文件中使用verbose=true打开日志记录,并在日志文件中使用tail.exe。它将向您显示它在数据库上执行的实际查询。实际上不是!我发誓我已经检查了三次了,但我还是错过了。但不幸的是,执行仍然缓慢。索引包含ActionName、CustomerAppId和ActionDate。使用AppId&Date或AppId&ActionName从shell进行分组速度很快,但从代码来看,两者都很慢。谢谢你的详细提示。我得查一查。别忘了你可以上传有用的评论和答案;使用Mongo2.4,我也可以使用带有二进制表示的GUI的聚合框架。我怀疑冗长可能会有帮助,因为我最近也去过那里。驱动程序中缺少总体支持是非常不方便的。它更脆弱,意味着丑陋的参数替换。有一个使用linq获得聚合支持的票证,但是它被关闭了,因为使用上面使用的方法是可能的。就我个人而言,我不认为这是令人满意的,你也听不到。如果你读了评论,我不明白为什么它被关闭了。它需要在IMHO中重新打开。我最后编写了一个教程,其中展示了将聚合框架与C结合使用的示例。希望人们能够复制和粘贴这些框架,并使用它们来构建自己的管道@cirrus支持linq到聚合框架还有一个悬而未决的问题,请看这里的问题。我怀疑冗长可能会有帮助,因为我最近也去过那里。驱动程序中缺少总体支持是非常不方便的。它更脆弱,意味着丑陋的参数替换。有一个使用linq获得聚合支持的票证,但是它被关闭了,因为使用上面使用的方法是可能的。个人
我不认为这是令人满意的,你也听不到。如果你读了评论,我不明白为什么它被关闭了。它需要在IMHO中重新打开。我最后编写了一个教程,其中展示了将聚合框架与C结合使用的示例。希望人们能够复制和粘贴这些框架,并使用它们来构建自己的管道@cirrus支持linq到聚合框架还有一个悬而未决的问题请参见此处的问题