当 $sort 和 $match 同时使用时,AWS DocumentDB 不使用索引

问题描述

DocumentDB 忽略任何字段的索引而不是排序

db.requests.aggregate([
    { $match: {'deviceid': '5f68c9c1-73c1-e5cb-7a0b-90be2f80a332'}},{ $sort: { 'Timestamp': 1 } }
])

有用信息:

> explain('executionStats')
{
    "queryPlanner" : {
        "plannerVersion" : 1,"namespace" : "admin_portal.requests","winningPlan" : {
            "stage" : "IXSCAN","indexName" : "Timestamp_1","direction" : "forward"
        }
    },"executionStats" : {
        "executionSuccess" : true,"executionTimeMillis" : "398883.755","planningTimeMillis" : "0.274","executionStages" : {
            "stage" : "IXSCAN","nReturned" : "20438","executionTimeMillisEstimate" : "398879.028","serverInfo" : {
       ...
    },"ok" : 1.0,"operationTime" : Timestamp(1622585939,1)
}
> db.requests.getIndexKeys()
[
    {
        "_id" : 1
    },{
        "Timestamp" : 1
    },{
        "deviceid" : 1
    }
]

当我在不排序的情况下查询文档或使用 findsort 函数而不是聚合时,它工作正常。

重要说明: 它也适用于原始 MongoDB 实例,但不适用于 DocumentDB

解决方法

这更多是“DocumentDB 如何选择查询计划”一类的问题。 有很多关于 Mongo 如何在 stackoverflow 上does 的答案。

很明显,基于数据分布的失败试验可能会选择“错误”的索引,这里的问题是 DocumentDB 添加了 unknown layer

Amazon DocumentDB 在专门构建的数据库引擎上模拟 MongoDB 4.0 API,该引擎利用分布式、容错、自我修复的存储系统。因此,Amazon DocumentDB 和 MongoDB 之间的查询计划和 explain() 可能会有所不同。想要控制查询计划的客户可以使用 $hint 运算符来强制选择首选索引。

他们声称由于这一层差异可能会发生。

现在我们明白了为什么选择了错误的索引(有点)。我们能做些什么?除非您想以某种方式删除或重建索引,否则您需要为管道使用 hint 选项。

db.collection.aggregate(pipeline,{hint: "index_name"})