mongodb索引已创建,但在查询时未使用



希望这不是一个愚蠢的问题。我正在mongodb上创建一个包含字符串的字段的复合索引。在运行索引创建之后,我没有看到通过db.currentOp()创建索引的进程,但是如果我运行getIndexes(),我确实看到了索引。

db.sampledb.createIndex(
{
"DevIdent.ParametersExt. ID": 1,
"DevIdent.Parameters.Type": 1,
"MetaData.SessionName": 1
},
{
background: false,
name: "sample",
}
)

使用explain运行这个查询,我总是得到COLLSCAN,我从来没有看到索引扫描,而不是COLLSCAN:

db.sampledb.aggregate([
{
"$match": {
"DevIdent.ParametersExt.ID": { "$regex": ".*22~44.*" },
"DevIdent.Parameters.Type": { "$ne": "TYPICAL" },
"MetaData.SessionName": "2021_02_09_13_31_03"
}
}
])

我错过了一些基本的东西吗?

这个匹配过滤器是问题所在:

"DevIdent.ParametersExt.ID": { "$regex": ".*22~44.*" }

您正在DevIdent.ParametersExt.ID字段中的任何位置搜索文本22~44。问题是,如果搜索可以从字段的最开头开始,则只能使用基于b树的索引,而这里的情况并非如此。

但是,没有理由不能在其他两个字段上使用索引。但是,由于您在一个不能使用的字段上启动了多列索引,因此Mongo选择根本不使用该索引。

您可以考虑只在其他两个字段上定义索引:

db.sampledb.createIndex({
"DevIdent.Parameters.Type": 1,
"MetaData.SessionName": 1
},
{
background:false,
name: "sample",
});

假设这两个字段具有很高的基数(即它们非常严格),那么Mongo可能会选择使用索引,尽管第三个字段有正则表达式条件。

索引只能用于"前缀"^....regexp。我发现https://docs.mongodb.com/manual/reference/operator/query/regex/#index-use上的文档对此非常清楚,所以我将在这里引用它:

对于区分大小写的正则表达式查询,如果存在字段,然后MongoDB匹配正则表达式值,这可能比集合扫描更快。如果正则表达式是"前缀",则可以进行进一步优化表达式",这意味着所有潜在的匹配都从相同的字符串。这允许MongoDB从中构建一个"范围"前缀,并且只匹配落在索引中的那些值

以A开头的正则表达式是"前缀表达式"插入符号(^)或左锚( a),后跟一个简单的符号。例如,正则表达式/^abc。*/将通过匹配进行优化仅针对以abc开头的索引中的值。

此外,当/^a/,/^a/。/和/^a。$/match等价字符串,它们有不同的性能特征。所有这些如果存在合适的索引,表达式使用索引;然而,/^。/和/^a。$/比较慢。/^a/匹配后停止扫描前缀。

每个人发布的答案对于索引的低效使用都是正确的,但它仍然应该在解释计划中遇到IXSCAN,因此我做了一个测试。

db.sampledb.createIndex(
{
"DevIdent.ParametersExt. ID": 1,
"DevIdent.Parameters.Type": 1,
"MetaData.SessionName": 1
},
{
background: false,
name: "sample",
}
)

这是您的命令,在DevIdent.ParametersExt. & ID之间有一些空格,这导致了一个问题,但是您仍然无法在没有空格的情况下创建一个新的索引,给出了重复的错误。把这个索引全部删除,然后创建一个不带空格的新索引。

编辑:学生错误,删除名字部分,你应该能够创建两个索引,在树中它是简单的字段名使用各自的BSON类型存储的字符串,因此使用空格和不空格分别是两个索引

db.sampledb.createIndex(
{
"DevIdent.ParametersExt.ID": 1,
"DevIdent.Parameters.Type": 1,
"MetaData.SessionName": 1
},
{
background: false,
name: "sample",
}
)  

现在试试你的聚合命令,对我有用。

{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test_content.test4",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [ 
{
"MetaData.SessionName" : {
"$eq" : "2021_02_09_13_31_03"
}
}, 
{
"DevIdent.ParametersExt.ID" : {
"$regex" : ".*22~44.*"
}
}, 
{
"DevIdent.Parameters.Type" : {
"$not" : {
"$eq" : "TYPICAL"
}
}
}
]
},
"optimizedPipeline" : true,
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"filter" : {
"DevIdent.ParametersExt.ID" : {
"$regex" : ".*22~44.*"
}
},
"keyPattern" : {
"DevIdent.ParametersExt.ID" : 1.0,
"DevIdent.Parameters.Type" : 1.0,
"MetaData.SessionName" : 1.0
},
"indexName" : "sample",
"isMultiKey" : false,
"multiKeyPaths" : {
"DevIdent.ParametersExt.ID" : [],
"DevIdent.Parameters.Type" : [],
"MetaData.SessionName" : []
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"DevIdent.ParametersExt.ID" : [ 
"["", {})", 
"[/.*22~44.*/, /.*22~44.*/]"
],
"DevIdent.Parameters.Type" : [ 
"[MinKey, "TYPICAL")", 
"("TYPICAL", MaxKey]"
],
"MetaData.SessionName" : [ 
"["2021_02_09_13_31_03", "2021_02_09_13_31_03"]"
]
}
}
},

最新更新