Mongo Db似乎选择了“错误”索引(查询计划)

时间:2018-07-03 14:25:00

标签: mongodb performance mongodb-query

我正在查询mongo数据库集合,并且返回结果相当缓慢。 使用不同的查询,可以将相同的信息更快地拉出1000倍以上。不幸的是,我并不总是拥有快速查询所需的信息。

问题似乎与Mongo引擎似乎在查询中使用“错误”索引有关。

如果在$in子句中指定了数据,则具体地说,它不使用预期的索引。

我试图理解为什么mongo引擎选择它要执行的索引而不是“正确的”索引,以及我可以做什么(如果有的话)让Mongo引擎选择(我认为是)“正确的索引。

这是我的集合中定义的索引的(截断的)列表:

db.Documents.getIndexes()

// returns
[
    {
        "v" : 1,
        "key" : {
            "isActive" : 1,
            "data.type" : 1
        },
        "name" : "isActive_1_data.type_1",
        "ns" : "SoforCms.Documents",
        "partialFilterExpression" : {
            "isActive" : true
        }
    },
    {
        "v" : 1,
        "key" : {
            "isActive" : 1,
            "data.type" : 1,
            "data.identities" : 1
        },
        "name" : "isActive_1_data.type_1_data.identities_1",
        "ns" : "SoforCms.Documents",
        "partialFilterExpression" : {
            "isActive" : true,
            "data.type" : "legalDoc"
        }
    },
    ... other indexes removed for brevity
]

在以下查询中,使用第一个索引而不是第二个索引(导致性能不佳):

db.Documents.find({
    isActive: true, 
    'data.type':'legalDoc', 
    'data.identities': {'$in' : [{id: '41', type: 'legacy'},
                                 {id : "23140", type : "legacy" }]}
}).explain()

这将导致使用第一个索引的查询计划:

{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "SoforCms.Documents",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "$and" : [ 
                {
                    "data.type" : {
                        "$eq" : "legalDoc"
                    }
                }, 
                {
                    "isActive" : {
                        "$eq" : true
                    }
                }, 
                {
                    "data.identities" : {
                        "$in" : [ 
                            {
                                "id" : "23140",
                                "type" : "legacy"
                            }, 
                            {
                                "id" : "41",
                                "type" : "legacy"
                            }
                        ]
                    }
                }
            ]
        },
        "winningPlan" : {
            "stage" : "FETCH",
            "filter" : {
                "data.identities" : {
                    "$in" : [ 
                        {
                            "id" : "23140",
                            "type" : "legacy"
                        }, 
                        {
                            "id" : "41",
                            "type" : "legacy"
                        }
                    ]
                }
            },
            "inputStage" : {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "isActive" : 1,
                    "data.type" : 1
                },
                "indexName" : "isActive_1_data.type_1",
                "isMultiKey" : false,
                "isUnique" : false,
                "isSparse" : false,
                "isPartial" : true,
                "indexVersion" : 1,
                "direction" : "forward",
                "indexBounds" : {
                    "isActive" : [ 
                        "[true, true]"
                    ],
                    "data.type" : [ 
                        "[\"legalDoc\", \"legalDoc\"]"
                    ]
                }
            }
        },
        "rejectedPlans" : [ 
            {
                "stage" : "FETCH",
                "filter" : {
                    "data.identities" : {
                        "$in" : [ 
                            {
                                "id" : "23140",
                                "type" : "legacy"
                            }, 
                            {
                                "id" : "41",
                                "type" : "legacy"
                            }
                        ]
                    }
                },
                "inputStage" : {
                    "stage" : "IXSCAN",
                    "keyPattern" : {
                        "isActive" : 1,
                        "data.type" : 1,
                        "data.identities" : 1
                    },
                    "indexName" : "isActive_1_data.type_1_data.identities_1",
                    "isMultiKey" : true,
                    "isUnique" : false,
                    "isSparse" : false,
                    "isPartial" : true,
                    "indexVersion" : 1,
                    "direction" : "forward",
                    "indexBounds" : {
                        "isActive" : [ 
                            "[true, true]"
                        ],
                        "data.type" : [ 
                            "[\"legalDoc\", \"legalDoc\"]"
                        ],
                        "data.identities" : [ 
                            "[MinKey, MaxKey]"
                        ]
                    }
                }
            }, 
            // other rejected plans removed for brevity            
        ]
    },
    "serverInfo" : {
        ...
    },
    "ok" : 1.0
}

如果我仅查询一个文档,则使用预期的(第二个)索引,查询运行速度快10_000倍!

db.Documents.find({'isActive': true, 
                   'data.type':'legalDoc', 
                   'data.identities': {id: '41', type: 'legacy'}})

欢迎提供有关替代索引定义或替代查询方式的任何建议。

当前,运行几个查询一次获取一个文档而不是在查询中获取所有文档的效率要高得多,但这感觉很不对。

0 个答案:

没有答案