加速MongoDB聚合

时间:2014-05-02 12:33:56

标签: mongodb indexing aggregation-framework

我有一个带有以下结构的分片集合“my_collection”:

{ 
   "CREATED_DATE" : ISODate(...),
   "MESSAGE" : "Test Message",
   "LOG_TYPE": "EVENT"
}

mongoDB环境使用2个分片进行分片。使用LOG_TYPE上的Hashed分片键对上面的集合进行分片。 LOG_TYPE属性还有7种其他可能性。

我在“my_collection”中有100万个文档,我试图使用以下查询找到基于LOG_TYPE的文档数:

db.my_collection.aggregate([
    { "$group" :{ 
        "_id": "$LOG_TYPE",
        "COUNT": { "$sum":1 }
    }}
])

但这让我得到了大约3秒的结果。有没有办法改善这个?此外,当我运行explain命令时,它显示没有使用索引。 group命令是否不使用索引?

2 个答案:

答案 0 :(得分:8)

目前,聚合框架可以采取哪些措施来提高查询性能,但您可以通过以下方式提供帮助:

db.my_collection.aggregate([
    { "$sort" : { "LOG_TYPE" : 1 } },
    { "$group" :{ 
        "_id": "$LOG_TYPE",
        "COUNT": { "$sum":1 }
    }}
])

通过在LOG_TYPE上添加排序,您将成为"强制"优化器使用LOG_TYPE上的索引来按顺序获取文档。这将以多种方式改善性能,但根据使用的版本而有所不同。

对于实际数据,如果您对进入$ group阶段的数据进行了排序,则会提高总计累积的效率。您可以看到不同的查询计划,其中$ sort将使用分片键索引。这在实际性能方面的改进将取决于每个"桶中的值的数量。 - 一般来说LOG_TYPE只有七个不同的值会使它成为一个非常糟糕的分片键,但它确实意味着下面的代码很可能比甚至优化的聚合快得多:

db.my_collection.distinct("LOG_TYPE").forEach(function(lt) {
   print(db.my_collection.count({"LOG_TYPE":lt});
});

答案 1 :(得分:0)

在MongoDB中你可以做的事情有限,在一天结束时这可能是一个超出MongoDB本身的物理问题,可能是延迟导致configsrvs不及时响应或结果从分片带回来太慢了。

但是,您可以通过使用覆盖查询来解决一些性能问题。由于你实际上在LOG_TYPE上进行分片,你已经有了一个索引(在你可以对其进行分片之前需要),不仅如此,聚合框架将自动添加projection以便赢得&#39 ; t帮助。

MongoDB可能需要与每个分片进行通信以获得结果,否则称为分散和聚集操作。

$group本身不会使用索引。

这是我在2.4.9的结果:

> db.t.ensureIndex({log_type:1})
> db.t.runCommand("aggregate", {pipeline: [{$group:{_id:'$log_type'}}], explain: true})
{
        "serverPipeline" : [
                {
                        "query" : {

                        },
                        "projection" : {
                                "log_type" : 1,
                                "_id" : 0
                        },
                        "cursor" : {
                                "cursor" : "BasicCursor",
                                "isMultiKey" : false,
                                "n" : 1,
                                "nscannedObjects" : 1,
                                "nscanned" : 1,
                                "nscannedObjectsAllPlans" : 1,
                                "nscannedAllPlans" : 1,
                                "scanAndOrder" : false,
                                "indexOnly" : false,
                                "nYields" : 0,
                                "nChunkSkips" : 0,
                                "millis" : 0,
                                "indexBounds" : {

                                },
                                "allPlans" : [
                                        {
                                                "cursor" : "BasicCursor",
                                                "n" : 1,
                                                "nscannedObjects" : 1,
                                                "nscanned" : 1,
                                                "indexBounds" : {

                                                }
                                        }
                                ],
                                "server" : "ubuntu:27017"
                        }
                },
                {
                        "$group" : {
                                "_id" : "$log_type"
                        }
                }
        ],
        "ok" : 1
}

这是2.6:

的结果
> use gthtg
switched to db gthtg
> db.t.insert({log_type:"fdf"})
WriteResult({ "nInserted" : 1 })
> db.t.ensureIndex({log_type: 1})
{ "numIndexesBefore" : 2, "note" : "all indexes already exist", "ok" : 1 }
> db.t.runCommand("aggregate", {pipeline: [{$group:{_id:'$log_type'}}], explain: true})
{
        "stages" : [
                {
                        "$cursor" : {
                                "query" : {

                                },
                                "fields" : {
                                        "log_type" : 1,
                                        "_id" : 0
                                },
                                "plan" : {
                                        "cursor" : "BasicCursor",
                                        "isMultiKey" : false,
                                        "scanAndOrder" : false,
                                        "allPlans" : [
                                                {
                                                        "cursor" : "BasicCursor",
                                                        "isMultiKey" : false,
                                                        "scanAndOrder" : false
                                                }
                                        ]
                                }
                        }
                },
                {
                        "$group" : {
                                "_id" : "$log_type"
                        }
                }
        ],
        "ok" : 1
}