我有一个带有以下结构的分片集合“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命令是否不使用索引?
答案 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
}