按 ISODate 聚合查询性能排序

aggregate query performance sorting by ISODate

我有这种简单的聚合查询

db.SomeCollection.aggregate([{
  "$match": {
    "Id": "someId"
  }
}, {
  "$sort": {
    "someISODatePropertyName": 1
  }
}, {
  "$unwind": {
    "path": "$somePropertyName"
  }
}], {
  allowDiskUse: true
})

此查询 returns 最多 50 个项目,需要 10 秒才能完成。

如果我只是将排序 属性 更改为数字:

db.SomeCollection.aggregate([{
  "$match": {
    "Id": "someId"
  }
}, {
  "$sort": {
    "someNumericPropertyName": 1
  }
}, {
  "$unwind": {
    "path": "$somePropertyName"
  }
}], {
  allowDiskUse: true
})

查询需要几毫秒才能完成。

ISODate 属性是否存在任何排序问题?

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

谢谢。

更新

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

{
    "waitedMS" : NumberLong(0),
    "stages" : [ 
        {
            "$cursor" : {
                "query" : {
                    "StreamId" : "5b8cc895-c626-5994-95d4-b9ac89fb66ed"
                },
                "sort" : {
                    "CommitStamp" : 1
                },
                "queryPlanner" : {
                    "plannerVersion" : 1,
                    "namespace" : "vrp-events-prod.Commits",
                    "indexFilterSet" : false,
                    "parsedQuery" : {
                        "StreamId" : {
                            "$eq" : "5b8cc895-c626-5994-95d4-b9ac89fb66ed"
                        }
                    },
                    "winningPlan" : {
                        "stage" : "FETCH",
                        "filter" : {
                            "StreamId" : {
                                "$eq" : "5b8cc895-c626-5994-95d4-b9ac89fb66ed"
                            }
                        },
                        "inputStage" : {
                            "stage" : "IXSCAN",
                            "keyPattern" : {
                                "CommitStamp" : 1
                            },
                            "indexName" : "CommitStamp_Index",
                            "isMultiKey" : false,
                            "isUnique" : false,
                            "isSparse" : false,
                            "isPartial" : false,
                            "indexVersion" : 1,
                            "direction" : "forward",
                            "indexBounds" : {
                                "CommitStamp" : [ 
                                    "[MinKey, MaxKey]"
                                ]
                            }
                        }
                    },
                    "rejectedPlans" : []
                }
            }
        }, 
        {
            "$unwind" : {
                "path" : "$Events"
            }
        }
    ],
    "ok" : 1
}

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

db.collection.createIndex("someISODatePropertyName": 1 或 -1)

尝试一下,它总是对我产生巨大的影响。

更新:

假设这不会大大降低您的写入查询速度,请添加一个涵盖匹配和排序的索引:

db.xxx.createIndex({"StreamId": 1, "CommitStamp": 1});

我在我的 collection 上测试了它,它将查询从 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" : [ ]
                                }