MongoDB不使用$ in或$或查询的索引

时间:2017-05-08 22:47:12

标签: mongodb mongodb-query database

我有一个包含大约350k文档的MongoDB集合,我正在基于其中一个整数字段进行简单的计数查询,通常使用$in。该字段使用db.myColl.createIndex({indexedField: 1})db.myColl.createIndex({indexedField: -1})编制索引。

当我运行匹配一个值的查询时,响应很快就会出现,如预期的那样:

> db.myColl.explain("executionStats").count({indexedField: 1})
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "myDb.myColl",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "indexedField" : {
                                "$eq" : 1
                        }
                },
                "winningPlan" : {
                        "stage" : "COUNT",
                        "inputStage" : {
                                "stage" : "COUNT_SCAN",
                                "keyPattern" : {
                                        "indexedField" : 1
                                },
                                "indexName" : "indexedField_1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "indexedField" : [ ]
                                },
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "indexBounds" : {
                                        "startKey" : {
                                                "indexedField" : 1
                                        },
                                        "startKeyInclusive" : true,
                                        "endKey" : {
                                                "indexedField" : 1
                                        },
                                        "endKeyInclusive" : true
                                }
                        }
                },
                "rejectedPlans" : [ ]
        },
        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 0,
                "executionTimeMillis" : 171,
                "totalKeysExamined" : 354783,
                "totalDocsExamined" : 0,
                "executionStages" : {
                        "stage" : "COUNT",
                        "nReturned" : 0,
                        "executionTimeMillisEstimate" : 101,
                        "works" : 354783,
                        "advanced" : 0,
                        "needTime" : 354782,
                        "needYield" : 0,
                        "saveState" : 2772,
                        "restoreState" : 2772,
                        "isEOF" : 1,
                        "invalidates" : 0,
                        "nCounted" : 354782,
                        "nSkipped" : 0,
                        "inputStage" : {
                                "stage" : "COUNT_SCAN",
                                "nReturned" : 354782,
                                "executionTimeMillisEstimate" : 91,
                                "works" : 354783,
                                "advanced" : 354782,
                                "needTime" : 0,
                                "needYield" : 0,
                                "saveState" : 2772,
                                "restoreState" : 2772,
                                "isEOF" : 1,
                                "invalidates" : 0,
                                "keysExamined" : 354783,
                                "keyPattern" : {
                                        "indexedField" : 1
                                },
                                "indexName" : "indexedField_1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "indexedField" : [ ]
                                },
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "indexBounds" : {
                                        "startKey" : {
                                                "indexedField" : 1
                                        },
                                        "startKeyInclusive" : true,
                                        "endKey" : {
                                                "indexedField" : 1
                                        },
                                        "endKeyInclusive" : true
                                }
                        }
                }
        },
        "serverInfo" : {
                "host" : "...",
                "port" : 27017,
                "version" : "3.4.4",
                "gitVersion" : "888390515874a9debd1b6c5d36559ca86b44babd"
        },
        "ok" : 1
}

但是,当我尝试使用indexedField查询$in的多个值时,它会慢慢爬行:

> db.myColl.explain("executionStats").count({indexedField: {$in: [1, 2]}})
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "myDb.myColl",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "indexedField" : {
                                "$in" : [
                                        1,
                                        2
                                ]
                        }
                },
                "winningPlan" : {
                        "stage" : "FETCH",
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "keyPattern" : {
                                        "indexedField" : 1
                                },
                                "indexName" : "indexedField_1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "indexedField" : [ ]
                                },
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "indexedField" : [
                                                "[1.0, 1.0]",
                                                "[2.0, 2.0]"
                                        ]
                                }
                        }
                },
                "rejectedPlans" : [
                        {
                                "stage" : "FETCH",
                                "inputStage" : {
                                        "stage" : "IXSCAN",
                                        "keyPattern" : {
                                                "indexedField" : -1
                                        },
                                        "indexName" : "indexedField_-1",
                                        "isMultiKey" : false,
                                        "multiKeyPaths" : {
                                                "indexedField" : [ ]
                                        },
                                        "isUnique" : false,
                                        "isSparse" : false,
                                        "isPartial" : false,
                                        "indexVersion" : 2,
                                        "direction" : "forward",
                                        "indexBounds" : {
                                                "indexedField" : [
                                                        "[2.0, 2.0]",
                                                        "[1.0, 1.0]"
                                                ]
                                        }
                                }
                        }
                ]
        },
        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 354782,
                "executionTimeMillis" : 215153,
                "totalKeysExamined" : 354782,
                "totalDocsExamined" : 354782,
                "executionStages" : {
                        "stage" : "FETCH",
                        "nReturned" : 354782,
                        "executionTimeMillisEstimate" : 214871,
                        "works" : 354783,
                        "advanced" : 354782,
                        "needTime" : 0,
                        "needYield" : 0,
                        "saveState" : 11371,
                        "restoreState" : 11371,
                        "isEOF" : 1,
                        "invalidates" : 0,
                        "docsExamined" : 354782,
                        "alreadyHasObj" : 0,
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "nReturned" : 354782,
                                "executionTimeMillisEstimate" : 748,
                                "works" : 354783,
                                "advanced" : 354782,
                                "needTime" : 0,
                                "needYield" : 0,
                                "saveState" : 11371,
                                "restoreState" : 11371,
                                "isEOF" : 1,
                                "invalidates" : 0,
                                "keyPattern" : {
                                        "indexedField" : 1
                                },
                                "indexName" : "indexedField_1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "indexedField" : [ ]
                                },
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "indexedField" : [
                                                "[1.0, 1.0]",
                                                "[2.0, 2.0]"
                                        ]
                                },
                                "keysExamined" : 354782,
                                "seeks" : 1,
                                "dupsTested" : 0,
                                "dupsDropped" : 0,
                                "seenInvalidated" : 0
                        }
                }
        },
        "serverInfo" : {
                "host" : "...",
                "port" : 27017,
                "version" : "3.4.4",
                "gitVersion" : "888390515874a9debd1b6c5d36559ca86b44babd"
        },
        "ok" : 1
}

使用$or代替$in会产生类似的错误结果:

> db.myColl.explain("executionStats").count({$or: [{indexedField: 1}, {indexedField: 2}] })
{
        "queryPlanner" : {
                "plannerVersion" : 1,
                "namespace" : "myDb.myColl",
                "indexFilterSet" : false,
                "parsedQuery" : {
                        "$or" : [
                                {
                                        "indexedField" : {
                                                "$eq" : 1
                                        }
                                },
                                {
                                        "indexedField" : {
                                                "$eq" : 2
                                        }
                                }
                        ]
                },
                "winningPlan" : {
                        "stage" : "COUNT",
                        "inputStage" : {
                                "stage" : "SUBPLAN",
                                "inputStage" : {
                                        "stage" : "FETCH",
                                        "inputStage" : {
                                                "stage" : "IXSCAN",
                                                "keyPattern" : {
                                                        "indexedField" : 1
                                                },
                                                "indexName" : "indexedField_1",
                                                "isMultiKey" : false,
                                                "multiKeyPaths" : {
                                                        "indexedField" : [ ]
                                                },
                                                "isUnique" : false,
                                                "isSparse" : false,
                                                "isPartial" : false,
                                                "indexVersion" : 2,
                                                "direction" : "forward",
                                                "indexBounds" : {
                                                        "indexedField" : [
                                                                "[1.0, 1.0]",
                                                                "[2.0, 2.0]"
                                                        ]
                                                }
                                        }
                                }
                        }
                },
                "rejectedPlans" : [ ]
        },
        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 0,
                "executionTimeMillis" : 219269,
                "totalKeysExamined" : 354782,
                "totalDocsExamined" : 354782,
                "executionStages" : {
                        "stage" : "COUNT",
                        "nReturned" : 0,
                        "executionTimeMillisEstimate" : 219170,
                        "works" : 354783,
                        "advanced" : 0,
                        "needTime" : 354782,
                        "needYield" : 0,
                        "saveState" : 11384,
                        "restoreState" : 11384,
                        "isEOF" : 1,
                        "invalidates" : 0,
                        "nCounted" : 354782,
                        "nSkipped" : 0,
                        "inputStage" : {
                                "stage" : "SUBPLAN",
                                "nReturned" : 354782,
                                "executionTimeMillisEstimate" : 219090,
                                "works" : 354783,
                                "advanced" : 354782,
                                "needTime" : 0,
                                "needYield" : 0,
                                "saveState" : 11384,
                                "restoreState" : 11384,
                                "isEOF" : 1,
                                "invalidates" : 0,
                                "inputStage" : {
                                        "stage" : "FETCH",
                                        "nReturned" : 354782,
                                        "executionTimeMillisEstimate" : 219040,
                                        "works" : 354783,
                                        "advanced" : 354782,
                                        "needTime" : 0,
                                        "needYield" : 0,
                                        "saveState" : 11383,
                                        "restoreState" : 11383,
                                        "isEOF" : 1,
                                        "invalidates" : 0,
                                        "docsExamined" : 354782,
                                        "alreadyHasObj" : 0,
                                        "inputStage" : {
                                                "stage" : "IXSCAN",
                                                "nReturned" : 354782,
                                                "executionTimeMillisEstimate" : 686,
                                                "works" : 354783,
                                                "advanced" : 354782,
                                                "needTime" : 0,
                                                "needYield" : 0,
                                                "saveState" : 11383,
                                                "restoreState" : 11383,
                                                "isEOF" : 1,
                                                "invalidates" : 0,
                                                "keyPattern" : {
                                                        "indexedField" : 1
                                                },
                                                "indexName" : "indexedField_1",
                                                "isMultiKey" : false,
                                                "multiKeyPaths" : {
                                                        "indexedField" : [ ]
                                                },
                                                "isUnique" : false,
                                                "isSparse" : false,
                                                "isPartial" : false,
                                                "indexVersion" : 2,
                                                "direction" : "forward",
                                                "indexBounds" : {
                                                        "indexedField" : [
                                                                "[1.0, 1.0]",
                                                                "[2.0, 2.0]"
                                                        ]
                                                },
                                                "keysExamined" : 354782,
                                                "seeks" : 1,
                                                "dupsTested" : 0,
                                                "dupsDropped" : 0,
                                                "seenInvalidated" : 0
                                        }
                                }
                        }
                }
        },
        "serverInfo" : {
                "host" : "...",
                "port" : 27017,
                "version" : "3.4.4",
                "gitVersion" : "888390515874a9debd1b6c5d36559ca86b44babd"
        },
        "ok" : 1
}

知道这里出了什么问题吗?

您应该可以通过将以下脚本应用于Mongo安装来重现此问题。

创建文件create_test_database.js

db.indexTestColl.createIndex({indexedField: 1});

var RECORDS_TO_CREATE = 5000000;

for (var i = 0; i < RECORDS_TO_CREATE; i++)
{
    // Populate indexedField with random numbers [1 - 3].
    db.indexTestColl.insertOne({"indexedField": NumberInt((Math.random() * 10) % 3 + 1)});
    if ((i + 1) % 10000 == 0) print("Inserted " + (i + 1) + " documents.");
}

创建并填充集合:

mongo localhost:27017/indexTestDb create_test_database.js

然后用这些查询测试它:

use indexTestDb
db.indexTestColl.explain("executionStats").count({indexedField: 1})
db.indexTestColl.explain("executionStats").count({indexedField: {$in: [1, 2]}})
db.indexTestColl.explain("executionStats").count({$or: [{indexedField: 1}, {indexedField: 2}] })

我是否正确假设$ in和$或查询应该从索引中受益?

0 个答案:

没有答案