MongoDB是否使用索引,explian()的结果该怎样分析?

  1. 在使用MOngoDB时,目前需要用查询条件和_id来分页,数据库有一个birthDay_str_1_status_1_activeTime_1这三个字段的索引,我的查询条件是:

    db.getCollection('T_User').find({
        "birthDay_str": "0727",
        "status": "APPLY",
        "_id": {
            $gte: "570e08ca00b04947c827ea2e"
        }
    }).sort({
        "_id": 1
    }).explain()

    返回结果如下,对mongoDB索引不是很了解,谁能回答下底下的内容是什么意思

  2. 返回结果如下:

{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "ossDev.T_User",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "$and" : [ 
                {
                    "birthDay_str" : {
                        "$eq" : "0727"
                    }
                }, 
                {
                    "status" : {
                        "$eq" : "APPLY"
                    }
                }, 
                {
                    "_id" : {
                        "$gte" : "570e08ca00b04947c827ea2e"
                    }
                }
            ]
        },
        "winningPlan" : {
            "stage" : "SORT",
            "sortPattern" : {
                "_id" : 1.0
            },
            "inputStage" : {
                "stage" : "SORT_KEY_GENERATOR",
                "inputStage" : {
                    "stage" : "FETCH",
                    "filter" : {
                        "_id" : {
                            "$gte" : "570e08ca00b04947c827ea2e"
                        }
                    },
                    "inputStage" : {
                        "stage" : "IXSCAN",
                        "keyPattern" : {
                            "birthDay_str" : 1.0,
                            "status" : 1.0,
                            "activeTime" : 1.0
                        },
                        "indexName" : "birthDay_str_1_status_1_activeTime_1",
                        "isMultiKey" : false,
                        "isUnique" : false,
                        "isSparse" : false,
                        "isPartial" : false,
                        "indexVersion" : 1,
                        "direction" : "forward",
                        "indexBounds" : {
                            "birthDay_str" : [ 
                                "[\"0727\", \"0727\"]"
                            ],
                            "status" : [ 
                                "[\"APPLY\", \"APPLY\"]"
                            ],
                            "activeTime" : [ 
                                "[MinKey, MaxKey]"
                            ]
                        }
                    }
                }
            }
        },
        "rejectedPlans" : [ 
            {
                "stage" : "FETCH",
                "filter" : {
                    "$and" : [ 
                        {
                            "birthDay_str" : {
                                "$eq" : "0727"
                            }
                        }, 
                        {
                            "status" : {
                                "$eq" : "APPLY"
                            }
                        }
                    ]
                },
                "inputStage" : {
                    "stage" : "IXSCAN",
                    "keyPattern" : {
                        "_id" : 1
                    },
                    "indexName" : "_id_",
                    "isMultiKey" : false,
                    "isUnique" : true,
                    "isSparse" : false,
                    "isPartial" : false,
                    "indexVersion" : 1,
                    "direction" : "forward",
                    "indexBounds" : {
                        "_id" : [ 
                            "[\"570e08ca00b04947c827ea2e\", {})"
                        ]
                    }
                }
            }, 
            {
                "stage" : "SORT",
                "sortPattern" : {
                    "_id" : 1.0
                },
                "inputStage" : {
                    "stage" : "SORT_KEY_GENERATOR",
                    "inputStage" : {
                        "stage" : "FETCH",
                        "filter" : {
                            "$and" : [ 
                                {
                                    "birthDay_str" : {
                                        "$eq" : "0727"
                                    }
                                }, 
                                {
                                    "_id" : {
                                        "$gte" : "570e08ca00b04947c827ea2e"
                                    }
                                }
                            ]
                        },
                        "inputStage" : {
                            "stage" : "IXSCAN",
                            "keyPattern" : {
                                "status" : 1.0
                            },
                            "indexName" : "status_1",
                            "isMultiKey" : false,
                            "isUnique" : false,
                            "isSparse" : false,
                            "isPartial" : false,
                            "indexVersion" : 1,
                            "direction" : "forward",
                            "indexBounds" : {
                                "status" : [ 
                                    "[\"APPLY\", \"APPLY\"]"
                                ]
                            }
                        }
                    }
                }
            }, 
            {
                "stage" : "SORT",
                "sortPattern" : {
                    "_id" : 1.0
                },
                "inputStage" : {
                    "stage" : "SORT_KEY_GENERATOR",
                    "inputStage" : {
                        "stage" : "FETCH",
                        "filter" : {
                            "$and" : [ 
                                {
                                    "birthDay_str" : {
                                        "$eq" : "0727"
                                    }
                                }, 
                                {
                                    "_id" : {
                                        "$gte" : "570e08ca00b04947c827ea2e"
                                    }
                                }
                            ]
                        },
                        "inputStage" : {
                            "stage" : "IXSCAN",
                            "keyPattern" : {
                                "status" : 1.0,
                                "userSequence" : 1.0
                            },
                            "indexName" : "status_1_userSequence_1",
                            "isMultiKey" : false,
                            "isUnique" : false,
                            "isSparse" : false,
                            "isPartial" : false,
                            "indexVersion" : 1,
                            "direction" : "forward",
                            "indexBounds" : {
                                "status" : [ 
                                    "[\"APPLY\", \"APPLY\"]"
                                ],
                                "userSequence" : [ 
                                    "[MinKey, MaxKey]"
                                ]
                            }
                        }
                    }
                }
            }
        ]
    },
    "serverInfo" : {
        "host" : "maomaodb02",
        "port" : 27017,
        "version" : "3.2.4",
        "gitVersion" : "e2ee9ffcf9f5a94fad76802e28cc978718bb7a30"
    },
    "ok" : 1.0
}

其中:

  "winningPlan" : {
            "stage" : "SORT",
            "sortPattern" : {
                "_id" : 1.0
            },
            "inputStage" : {
                "stage" : "SORT_KEY_GENERATOR",
                "inputStage" : {
                    "stage" : "FETCH",
                    "filter" : {
                        "_id" : {
                            "$gte" : "570e08ca00b04947c827ea2e"
                        }
                    },

显示的状态为SORT是什么意思,再往下面状态又为IXSCAN,请问是通过哪一块的信息,判断是否用到了索引?
同事stage状态为IXSCANFETCHSORT、分别代表什么意思?

阅读 10.1k
1 个回答

简单地讲,看到{stage: "SORT"}就代表有一个阶段是单独在做内存排序而没有用到索引。而看到IXSCAN和使用内存排序并不矛盾,这里用到索引是在用它过滤数据:

"indexBounds" : {
    "birthDay_str" : [ 
        "[\"0727\", \"0727\"]"
    ],
    "status" : [ 
        "[\"APPLY\", \"APPLY\"]"
    ],
    "activeTime" : [ 
        "[MinKey, MaxKey]"
    ]
}

所以查询部分是用到了birthDay_str_1_status_1_activeTime_1中的birthDay_str+status两个来过滤数据,当然你的条件中还有{_id: {$gte: "570e08ca00b04947c827ea2e"}},所以这个索引虽然命中了,但是只能说对你的查询有一定的帮助,效率怎么样还不好说(需要看explain("executionStats"))。不管怎么说,这个索引对排序是没有任何帮助的。
再来说FETCH。它的意思是如字面意思:抓取数据。假设你在A字段上建立了索引,这个索引是个BTree,但是你可以把它想象成一个排好序的数组,这样在做搜索的时候就可以折半查找,从而节省搜索时间,时间复杂度从O(n)变成O(log2(n)),这也是索引提高查询效率的原因由来。但是数组里面只有A字段的值,不可能也没有必要包含整个文档的内容,所以在数组中除了存放A的值外,系统会额外存一个data page,数据页,意思就是:当你需要A以外的其他值的时候去这里找整个文档。这样一来就有了FETCH这个动作。

我没有办法在这里解释怎么索引是如何工作的,但是你可以搜一些文档看看BTree索引的工作原理,相信会对索引如何工作有更好的理解。

最后提一下满足你那个查询和排序的最合适的索引是:

{
    birthDay_str: 1,
    status: 1,
    _id: 1
}

还有一点不知道是你手误或者是没有注意,默认情况下_idObjectId而不是字符串(除非你有特别修改),所以条件中的正确写法应该是:

"_id": {
    $gte: ObjectId("570e08ca00b04947c827ea2e")
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进