mongodb - mongodb:使用$all时,查询执行时间取决于输入参数的顺序
问题描述
我有一个具有以下结构的玩具 mongodb 集合
{
"operation" : {
"type" : "STACK"
},
"constraints" : [{
"partNumbers" : ["part", "part_1"]
}]
}
我想查询指定类型和partNumbers的文档,所以我写了这个查询
db.getCollection('toy').find({
"operation.type" : "STACK",
"constraints.partNumbers": {"$all": ["part_1", "part"]}
})
和索引
db.toy.ensureIndex( {
"operation.type": 1,
"constraints.partNumbers": 1,
})
我创建了一个包含数百万个文档的数据集,其中几乎所有文档在 partNumbers 数组中都有“部分”
查询非常快(需要 1 毫秒),但如果我交换“part”和“part1”,则需要很长时间(在我的数据集上超过 2 秒)。
看起来 mongodb 仅在我在查询的“$all”函数中传递的第一个元素上使用索引。
这是执行快速查询的 explain() 结果
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "factorysim.robofacturingservice",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"constraints" : {
"$elemMatch" : {
"$and" : [
{
"partNumbers" : {
"$size" : 2
}
},
{
"constraintType" : {
"$eq" : "PART_NUMBER_CONSTRAINT"
}
},
{
"partNumbers" : {
"$eq" : "part_1"
}
},
{
"partNumbers" : {
"$eq" : "part"
}
}
]
}
}
},
{
"operation.type" : {
"$eq" : "STACK"
}
}
]
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"constraints" : {
"$elemMatch" : {
"$and" : [
{
"partNumbers" : {
"$eq" : "part_1"
}
},
{
"partNumbers" : {
"$size" : 2
}
},
{
"constraintType" : {
"$eq" : "PART_NUMBER_CONSTRAINT"
}
},
{
"partNumbers" : {
"$eq" : "part"
}
}
]
}
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"operation.type" : 1.0,
"constraints.partNumbers" : 1.0
},
"indexName" : "operation.type_1_constraints.partNumbers_1",
"isMultiKey" : true,
"multiKeyPaths" : {
"operation.type" : [],
"constraints.partNumbers" : [
"constraints",
"constraints.partNumbers"
]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"operation.type" : [
"[\"STACK\", \"STACK\"]"
],
"constraints.partNumbers" : [
"[\"part_1\", \"part_1\"]"
]
}
}
},
"rejectedPlans" : []
},
"serverInfo" : {
"host" : "p1",
"port" : 27017,
"version" : "3.6.8",
"gitVersion" : "8e540c0b6db93ce994cc548f000900bdc740f80a"
},
"ok" : 1.0
}
对于执行缓慢的
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "factorysim.robofacturingservice",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"constraints" : {
"$elemMatch" : {
"$and" : [
{
"partNumbers" : {
"$size" : 2
}
},
{
"constraintType" : {
"$eq" : "PART_NUMBER_CONSTRAINT"
}
},
{
"partNumbers" : {
"$eq" : "part"
}
},
{
"partNumbers" : {
"$eq" : "part_1"
}
}
]
}
}
},
{
"operation.type" : {
"$eq" : "STACK"
}
}
]
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"constraints" : {
"$elemMatch" : {
"$and" : [
{
"partNumbers" : {
"$eq" : "part"
}
},
{
"partNumbers" : {
"$size" : 2
}
},
{
"constraintType" : {
"$eq" : "PART_NUMBER_CONSTRAINT"
}
},
{
"partNumbers" : {
"$eq" : "part_1"
}
}
]
}
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"operation.type" : 1.0,
"constraints.partNumbers" : 1.0
},
"indexName" : "operation.type_1_constraints.partNumbers_1",
"isMultiKey" : true,
"multiKeyPaths" : {
"operation.type" : [],
"constraints.partNumbers" : [
"constraints",
"constraints.partNumbers"
]
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"operation.type" : [
"[\"STACK\", \"STACK\"]"
],
"constraints.partNumbers" : [
"[\"part\", \"part\"]"
]
}
}
},
"rejectedPlans" : []
},
"serverInfo" : {
"host" : "p1",
"port" : 27017,
"version" : "3.6.8",
"gitVersion" : "8e540c0b6db93ce994cc548f000900bdc740f80a"
},
"ok" : 1.0
}
有没有一种方法可以编写独立于输入参数顺序的查询/索引组合?
解决方案
两个查询计划似乎是相同的,因此断言
索引的使用取决于输入数组的顺序
似乎没有证据支持。
推荐阅读
- spring - 无法运行 Spring 应用程序
- python - 如何在 python 3.X 中要求数独板输入?,我制作了一个数独求解器程序,但它只适用于我声明的板
- python - 寻找一种简单的方法来访问和导出到 xarray 对象中的多个数据变量的新数组
- azure - 用于检索 Azure 订阅名称、资源组、资源名称、资源类型、标签和位置的 KQL 查询
- javascript - 在添加行时动态检查 for 循环内表的高度
- node.js - JSON中的多词对象名称,节点红色
- c - 创建一个函数以将数据输入到结构中
- cvxpy - 如何使 cvxpy 支持 3d 变量
- spring - 使用 Maven 命令行参数填充的 Spring 值
- javascript - 如何使用表单提交的标头(在 Web 应用程序中)将 JWT 发送回服务器?