MongoDB: запрос нескольких полей и индексация - PullRequest
1 голос
/ 21 июня 2020

Я использую MongoDB через mon goose.

  1. Что происходит, когда вы запрашиваете индексированное поле с неиндексированным полем? См. Код ниже.

    // For example
    MyModel.find({ _id: '123', name: 'Jina'});
    

    Выполняет ли MongoDB сканирование коллекции или помогает ли индекс в повышении эффективности запроса? И отличается ли запрос от простого использования поля _id?

  2. Если MongoDB выполняет сканирование коллекции, когда вы запрашиваете неиндексированное поле. Ускоряет ли запрос нескольких неиндексированных полей скорость запроса, если сканирование коллекции все равно будет выполняться? Допустим, я запрашиваю пять неиндексированных полей, а не два (оба возвращают один и тот же документ (-ы)). Оба запроса выполняли одно и то же сканирование коллекции?

1 Ответ

2 голосов
/ 21 июня 2020

Чтобы понять, что происходит под капотом в запросах mon go, вы можете использовать explain. Например, рассмотрим следующий запрос: db.getCollection('users').find({"name":"ana"}), который запрашивает неиндексированное поле. Вы можете использовать объяснение этого запроса, как показано ниже:

db.getCollection('users').find({"name":"ana"}).explain("executionStats")

Часть результата:

"queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "anonymous-chat.users",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "name" : {
                "$eq" : "ana"
            }
        },
        "winningPlan" : {
            "stage" : "COLLSCAN",
            "filter" : {
                "name" : {
                    "$eq" : "ana"
                }
            },
            "direction" : "forward"
        },
        "rejectedPlans" : []
    },

Как видите, здесь у нас был COLLSCAN - сканирование коллекции. Теперь мы просто запрашиваем _id и видим результат:

db.getCollection('users').find({"_id":ObjectId("5ee9b6c125b9a9a426d9965f")}).explain("executionStats")

Вот результат:

"queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "anonymous-chat.users",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "_id" : {
                "$eq" : ObjectId("5ee9b6c125b9a9a426d9965f")
            }
        },
        "winningPlan" : {
            "stage" : "IDHACK"
        },
        "rejectedPlans" : []
    },

Как мы видим, у нас есть IDHACK при запросе только _id.

Теперь мы объединяем _id и name:

db.getCollection('users').find({"_id":ObjectId("5ee9b6c125b9a9a426d9965f"), "name":"ana"}).explain("executionStats")

Это результат:

 "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "anonymous-chat.users",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "$and" : [ 
                {
                    "_id" : {
                        "$eq" : ObjectId("5ee9b6c125b9a9a426d9965f")
                    }
                }, 
                {
                    "name" : {
                        "$eq" : "ana"
                    }
                }
            ]
        },
        "winningPlan" : {
            "stage" : "FETCH",
            "filter" : {
                "name" : {
                    "$eq" : "ana"
                }
            },
            "inputStage" : {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "_id" : 1
                },
                "indexName" : "_id_",
                "isMultiKey" : false,
                "multiKeyPaths" : {
                    "_id" : []
                },
                "isUnique" : true,
                "isSparse" : false,
                "isPartial" : false,
                "indexVersion" : 2,
                "direction" : "forward",
                "indexBounds" : {
                    "_id" : [ 
                        "[ObjectId('5ee9b6c125b9a9a426d9965f'), ObjectId('5ee9b6c125b9a9a426d9965f')]"
                    ]
                }
            }
        },
        "rejectedPlans" : []
    },

Как мы видим, индекс помог с производительностью запроса, так как у нас есть два этапы, этап IXSCAN (сканирование индекса) и этап FETCH, который фильтрует документы последнего этапа.

Теперь давайте запросим несколько неиндексированных полей, чтобы узнать о вашем втором вопросе:

db.getCollection('users').find({"name":"ana", "appId":1}).explain("executionStats")

"queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "anonymous-chat.users",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "$and" : [ 
                {
                    "appId" : {
                        "$eq" : 1.0
                    }
                }, 
                {
                    "name" : {
                        "$eq" : "ana"
                    }
                }
            ]
        },
        "winningPlan" : {
            "stage" : "COLLSCAN",
            "filter" : {
                "$and" : [ 
                    {
                        "appId" : {
                            "$eq" : 1.0
                        }
                    }, 
                    {
                        "name" : {
                            "$eq" : "ana"
                        }
                    }
                ]
            },
            "direction" : "forward"
        },
        "rejectedPlans" : []
    },

Есть только одно сканирование коллекции для нескольких полей, как мы видим выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...