3

我有一个简单的集合:

{
    "_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 秒内返回。

有什么我想念的吗?

感谢期待。

4

2 回答 2

4

从您编写的查询中可以看出,2.0 中的这种类型的聚合需要您运行 Map/Reduce。MongoDB 上的 Map/Reduce 有一些性能损失,之前在 SO 上已经介绍——基本上除非你能够跨集群并行化,否则你将通过 Spidermonkey 运行单线程 javascript——这不是一个快速的提议。由于您没有选择性,因此索引并没有真正的帮助-您只需要扫描整个索引以及可能的文档即可。

随着即将发布的 2.2(目前在撰写本文时的 rc1 中),您有一些选择。2.2 中引入的聚合框架(它是原生的,不是基于 JS 的 Map/Reduce)有一个内置的group 操作符,是专门为加速 MongoDB 中的这种操作而创建的。

我建议试一试 2.2,看看你的分组表现是否有所提高。我认为它看起来像这样(注意:未经测试):

db.alarm.aggregate(
    { $group : {
        _id : "$serverName",
        count : { $sum : 1 }
    }}
);
于 2012-08-21T21:23:37.800 回答
2

另一种选择,也许是目前最高效的解决方案,可能是使用 distinct() 命令并在客户端计算结果。 http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct

于 2012-08-21T21:25:44.237 回答