我有一个包含数百万个文档的集合,每个文档代表一个事件:{_id,product,timestamp}在我的查询中,我需要按产品分组,并以前10个为例。
"aggregate" : "product_events",
"pipeline" : [
{
"$match" : {
"timeEvent" : {
"$gt" : ISODate("2017-07-17T00:00:00Z")
}
}
},
{
"$group" : {
"_id" : "$product",
"count" : {
"$sum" : 1
}
}
},
{
"$sort" : {
"count" : -1
}
},
{
"$limit" : 10
}
]我的查询现在非常慢(10秒),我想知道是否有一种不同的存储数据的方法来优化这个查询?
db.product_events.explain("executionStats").aggregate([ {"$match" :
{"timeEvent" : {"$gt" : ISODate("2017-07-17T00:00:00Z")}}},{"$group" :
{"_id" : "$product","count" : {"$sum" : 1}}}, {"$project": {"_id": 1,
"count": 1}} , {"$sort" : {"count" : -1}},{"$limit" : 500}],
{"allowDiskUse": true})
{
"stages" : [
{
"$cursor" : {
"query" : {
"timeEvent" : {
"$gt" : ISODate("2017-07-17T00:00:00Z")
}
},
"fields" : {
"product" : 1,
"_id" : 0
},
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "mydb.product_events",
"indexFilterSet" : false,
"parsedQuery" : {
"timeEvent" : {
"$gt" : ISODate("2017-07-17T00:00:00Z")
}
},
"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"timeEvent" : {
"$gt" : ISODate("2017-07-17T00:00:00Z")
}
},
"direction" : "forward"
},
"rejectedPlans" : [ ]
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 2127315,
"executionTimeMillis" : 940,
"totalKeysExamined" : 0,
"totalDocsExamined" : 2127315,
"executionStages" : {
"stage" : "COLLSCAN",
"filter" : {
"timeEvent" : {
"$gt" : ISODate("2017-07-17T00:00:00Z")
}
},
"nReturned" : 2127315,
"executionTimeMillisEstimate" : 810,
"works" : 2127317,
"advanced" : 2127315,
"needTime" : 1,
"needYield" : 0,
"saveState" : 16620,
"restoreState" : 16620,
"isEOF" : 1,
"invalidates" : 0,
"direction" : "forward",
"docsExamined" : 2127315
}
}
}
},
{
"$group" : {
"_id" : "$product",
"count" : {
"$sum" : {
"$const" : 1
}
}
}
},
{
"$project" : {
"_id" : true,
"count" : true
}
},
{
"$sort" : {
"sortKey" : {
"count" : -1
},
"limit" : NumberLong(500)
}
}
],
"ok" : 1
}在我的索引下面
db.product_events.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "mydb.product_events"
},
{
"v" : 2,
"key" : {
"product" : 1,
"timeEvent" : -1
},
"name" : "product_1_timeEvent_-1",
"ns" : "mydb.product_events"
}
]发布于 2018-04-17 22:44:54
在集合的字段上创建索引有助于优化从数据库集合中检索数据的过程。
通常在字段上创建索引,根据特定条件将数据过滤到这些字段中。
包含在索引字段中的数据按特定顺序排序,一旦发现匹配,则在获取数据时,停止扫描其他文档,这使得获取数据的过程更快。
根据上述问题的描述,为了优化聚合查询的性能,请尝试在timeEvent字段上创建索引,因为timeEvent字段用作聚合管道的$match阶段的筛选器表达式。
发布于 2018-04-18 06:46:22
复合索引上的documentation说明如下。
db.products.createIndex( {“物品”:1,“股票”:1})
复合索引中列出的字段的顺序很重要。索引将包含对文档的引用,这些文档首先按项目字段的值排序,然后在项目字段的每个值中,再按股票字段的值排序。
除了支持与所有索引字段匹配的查询外,复合索引还可以支持与索引字段的前缀匹配的查询。也就是说,索引支持对item字段以及item和字段的查询。
您的product_1_timeEvent_-1索引如下所示:
{
"product" : 1,
"timeEvent" : -1
}这就是为什么它不能用于支持只过滤timeEvent的查询。
你必须得到排序的选项:
product字段timeEvent字段的附加索引。product字段上包含一些附加筛选器,以便使用现有索引)请记住,索引的任何创建/删除/修改也可能影响其他查询。因此,请确保正确地测试了您的更改。
https://stackoverflow.com/questions/49880624
复制相似问题