【问题标题】:MongoDB: Querying multiple fields and indexingMongoDB:查询多个字段和索引
【发布时间】:2020-10-11 03:49:03
【问题描述】:

我正在通过 mongoose 使用 MongoDB。

  1. 当您使用非索引字段查询索引字段时会发生什么?请参阅下面的代码。

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

    MongoDB 是否进行集合扫描或索引是否有助于提高查询效率?查询与仅使用 _id 字段有何不同?

  2. 如果 MongoDB 在您查询非索引字段时执行集合扫描。如果集合扫描完全一样,查询多个非索引字段是否会加快查询速度?假设我查询五个非索引字段而不是两个(都返回相同的文档)。两个查询是否执行相同的集合扫描?

【问题讨论】:

    标签: mongodb mongoose indexing mongodb-query


    【解决方案1】:

    要了解 mongo 查询的幕后情况,您可以使用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" : []
        },
    

    如我们所见,我们在查询 _id 时有IDHACK

    现在我们结合 _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" : []
        },
    

    正如我们在上面看到的,对于多个字段只有一个集合扫描。

    【讨论】:

      猜你喜欢
      • 2016-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-10
      • 1970-01-01
      • 2016-04-19
      • 2012-08-23
      • 1970-01-01
      相关资源
      最近更新 更多