我有一个简单的集合:
{
"_id" : ObjectId("5033cc15f31e20b76ca842c8"),
"_class" : "com.pandu.model.alarm.Alarm",
"serverName" : "CDCAWR009 Integration Service",
"serverAddress" : "cdcawr009.na.convergys.com",
"triggered" : ISODate("2012-01-28T05:09:03Z"),
"componentName" : "IntegrationService",
"summary" : "A device which is configured to be recorded is not being recorded.",
"details" : "Extension<153; 40049> on CDCAWR009 is currently not being recorded
properly; recording requested for the following reasons: ",
"priority" : "Major"
}
集合中将有大约数百万个此类文档。我试图按服务器名称分组并获取所有服务器名称的计数。从RDBMS查询的角度来看听起来很简单。
The query that I have come up with is
db.alarm.group( {key: { serverName:true }, reduce: function(obj,prev) { prev.count++ }, initial: { count: 0 }});
另外,我在serverName上添加了一个索引。
> db.alarm.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"ns" : "test.alarm",
"name" : "_id_"
},
{
"v" : 1,
"key" : {
"serverName" : 1
},
"ns" : "test.alarm",
"name" : "serverName_1"
}
]
然而,我在13秒后得到mongodb的回应。而在sql server中,类似的查询在4秒内返回,没有索引。
我有什么遗失的吗?
感谢您的期待。
答案 0 :(得分:4)
从您编写的查询中可以看出,2.0中的这种聚合类型要求您运行Map / Reduce。 MongoDB上的Map / Reduce有一些性能损失已经在SO before上得到了解决 - 基本上除非你能够跨群集并行化,你将通过Spidermonkey运行单线程javascript - 而不是一个快速的命题。由于您没有选择性,索引并没有真正帮助 - 您只需要扫描整个索引以及可能的文档。
随着即将发布的2.2(目前在编写本文时目前处于rc1),你有一些选择。 2.2中引入的aggregation framework(本机的,而不是基于JS的Map / Reduce)具有内置的group operator,专门用于加速MongoDB中的这种操作。
我建议给2.2打一针,看看你的分组表现是否有所改善。我认为它看起来像这样(注意:未经测试):
db.alarm.aggregate(
{ $group : {
_id : "$serverName",
count : { $sum : 1 }
}}
);
答案 1 :(得分:2)
另一种选择,也许是目前性能最佳的解决方案,可能是使用distinct()命令并计算客户端的结果。 http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct