Mongodb 按ISODate排序的聚合查询性能

Mongodb 按ISODate排序的聚合查询性能,mongodb,database-performance,isodate,Mongodb,Database Performance,Isodate,我有这种简单的聚合查询 db.SomeCollection.aggregate([{ "$match": { "Id": "someId" } }, { "$sort": { "someISODatePropertyName": 1 } }, { "$unwind": { "path": "$somePropertyName" } }], { allowDiskUse: true }) 此查询最多返回50个项目,需要10秒才能完成 如果我只是

我有这种简单的聚合查询

db.SomeCollection.aggregate([{
  "$match": {
    "Id": "someId"
  }
}, {
  "$sort": {
    "someISODatePropertyName": 1
  }
}, {
  "$unwind": {
    "path": "$somePropertyName"
  }
}], {
  allowDiskUse: true
})
此查询最多返回50个项目,需要10秒才能完成

如果我只是用数字更改sort属性:

db.SomeCollection.aggregate([{
  "$match": {
    "Id": "someId"
  }
}, {
  "$sort": {
    "someNumericPropertyName": 1
  }
}, {
  "$unwind": {
    "path": "$somePropertyName"
  }
}], {
  allowDiskUse: true
})
查询需要几毫秒才能完成

ISODate属性是否存在排序问题

我真的不明白为什么第一个版本要花这么长时间

多谢各位

更新

这是“explain”标志设置为true的查询结果(注意:在ISODate字段上有一个索引):


根据我的经验,在日期字段上没有索引的日期排序很慢。假设您经常阅读此集合,并且通常按日期排序,添加索引将是理想的解决方案

createIndex(“someISODatePropertyName”:1或-1)

试试看,这对我来说总是有很大的不同

更新:

假设这不会太慢您的写查询,请添加一个涵盖匹配和排序的索引:

createIndex({“StreamId”:1,“CommitStamp”:1})

我在我的集合上进行了测试,它将查询速度从15秒(使用日期索引)提高到不到一秒(使用新创建的索引)。仅供参考,我的最新解释显示:

"queryPlanner" : {
                                        "plannerVersion" : 1,
                                        "namespace" : "db.xxx",
                                        "indexFilterSet" : false,
                                        "parsedQuery" : {
                                                "id" : {
                                                        "$eq" : 122
                                                }
                                        },
                                        "winningPlan" : {
                                                "stage" : "FETCH",
                                                "inputStage" : {
                                                        "stage" : "IXSCAN",
                                                        "keyPattern" : {
                                                                "id" : 1,
                                                                "date" : 1
                                                        },
                                                        "indexName" : "id_1_date_1",
                                                        "isMultiKey" : false,
                                                        "direction" : "forward",
                                                        "indexBounds" : {
                                                                "id" : [
                                                                        "[122.0, 122.0]"
                                                                ],
                                                                "date" : [
                                                                        "[MinKey, MaxKey]"
                                                                ]
                                                        }
                                                }
                                        },
                                        "rejectedPlans" : [ ]
                                }

根据我的经验,在日期字段上没有索引的日期排序很慢。假设您经常阅读此集合,并且通常按日期排序,添加索引将是理想的解决方案

createIndex(“someISODatePropertyName”:1或-1)

试试看,这对我来说总是有很大的不同

更新:

假设这不会太慢您的写查询,请添加一个涵盖匹配和排序的索引:

createIndex({“StreamId”:1,“CommitStamp”:1})

我在我的集合上进行了测试,它将查询速度从15秒(使用日期索引)提高到不到一秒(使用新创建的索引)。仅供参考,我的最新解释显示:

"queryPlanner" : {
                                        "plannerVersion" : 1,
                                        "namespace" : "db.xxx",
                                        "indexFilterSet" : false,
                                        "parsedQuery" : {
                                                "id" : {
                                                        "$eq" : 122
                                                }
                                        },
                                        "winningPlan" : {
                                                "stage" : "FETCH",
                                                "inputStage" : {
                                                        "stage" : "IXSCAN",
                                                        "keyPattern" : {
                                                                "id" : 1,
                                                                "date" : 1
                                                        },
                                                        "indexName" : "id_1_date_1",
                                                        "isMultiKey" : false,
                                                        "direction" : "forward",
                                                        "indexBounds" : {
                                                                "id" : [
                                                                        "[122.0, 122.0]"
                                                                ],
                                                                "date" : [
                                                                        "[MinKey, MaxKey]"
                                                                ]
                                                        }
                                                }
                                        },
                                        "rejectedPlans" : [ ]
                                }

是的,我忘了提到我已经在那个字段上建立了索引(顺便说一句,不是在数字字段上…),我发现奇怪的是,在一个简单的排序操作中,数字字段和日期字段之间的性能有着巨大的差异。我正在考虑解决方案。我很惊讶这个指数还不够。您是否可以尝试将explain作为一个选项来运行查询,并查看它所说的内容?谢谢,我用explain查询结果更新了帖子。我还寻找了一些值,比如:totaldocsexandered,看看索引是否需要检查很多文档。我们为什么不尝试编写一个覆盖查询,它需要检查0个文档。删除date上的索引,然后在id上写一个索引,然后是date,看看是否可行。我今天要用这个测试一下,然后给你回复(我在加利福尼亚,现在是早上6点),我已经更新了我的答案。基本上,您的索引还需要覆盖StreamId的匹配。我希望这能奏效!但是,如果您要向该集合添加大量文档,请确保您的写入不会花费太长时间。是的,我忘了提到我已经在该字段上建立了索引(顺便说一句,不是在数字上…)我觉得很奇怪的是,在一个简单的排序操作中,数字字段和日期字段之间的性能有着巨大的差异。我正在考虑解决方案。我很惊讶这个指数还不够。您是否可以尝试将explain作为一个选项来运行查询,并查看它所说的内容?谢谢,我用explain查询结果更新了帖子。我还寻找了一些值,比如:totaldocsexandered,看看索引是否需要检查很多文档。我们为什么不尝试编写一个覆盖查询,它需要检查0个文档。删除date上的索引,然后在id上写一个索引,然后是date,看看是否可行。我今天要用这个测试一下,然后给你回复(我在加利福尼亚,现在是早上6点),我已经更新了我的答案。基本上,您的索引还需要覆盖StreamId的匹配。我希望这能奏效!但是,如果您要向该集合添加大量文档,请确保您的写入不会花费太长时间。