我有一个问题是为我的mongo查询生成正确的索引,这将避免SORT阶段。在我的情况下,我甚至不确定这是否可行。所以这是我的执行统计查询:
db.getCollection('test').find(
{
"$or" : [
{
"a" : { "$elemMatch" : { "_id" : { "$in" : [4577] } } },
"b" : { "$in" : [290] },
"c" : { "$in" : [35, 49, 57, 101, 161, 440] },
"d" : { "$lte" : 399 }
},
{
"e" : { "$elemMatch" : { "numbers" : { "$in" : ["1K0407151AC", "0K20N51150A"] } } },
"d" : { "$lte" : 399 }
}]
})
.sort({ "X" : 1, "d" : 1, "Y" : 1, "Z" : 1 }).explain("executionStats")
字段' m' ,' a'并且' e'是数组,这就是为什么' m'不包含在任何索引中。
如果查看execution stats屏幕截图,您会看到内存使用率非常接近最大值,不幸的是我遇到了因为32MB限制而无法执行查询的情况。
$或查询的第一部分的索引: { " a._id" :1, " X" :1, " d" :1, " Y" :1, " Z" :1, " B" :1, " C" :1 }
$或查询的第二部分的索引: { " e.numbers" :1, " X" :1, " d" :1, " Y" :1, " Z" :1 }
索引由查询使用,但不用于排序。而不是SORT阶段我也希望看到SORT_MERGE阶段,但现在没有成功。如果我在$或单独运行部分查询,他们可以使用索引来避免在内存中进行排序。作为一种解决方法,它是可以的,但我需要通过应用程序合并并求助结果。
MongoDB版本是3.4.2。我检查了that和that问题。我的查询是结果。可能我错过了什么?
编辑:mongo文档看起来像这样:
{
"_id" : "290_440_K760A03",
"Z" : "K760A03",
"c" : 440,
"Y" : "NPS",
"b" : 290,
"X" : "Schlussleuchte",
"e" : [
{
"..." : 184,
"numbers" : [
"0K20N51150A"
]
}
],
"a" : [
{
"_id" : 4577,
"..." : [
{
"..." : [
{
"..." : "R",
}
]
}
]
},
{
"_id" : 4578
}
],
"d" : 101,
"m" : [
"AT",
"BR",
"CH"
],
"moreFields":"..."
}
编辑2 :删除了提交的" m"从查询到降低复杂性和attached测试集合转储给想要帮助的人:)
答案 0 :(得分:0)
这是解决方案 - 我刚刚在我的测试集合中添加了一个文档,如您的问题所示(编辑部分)。然后我在下面创建了四个指数 -
1. {"m":1,"b":1,"c":1,"X":1,"d":1,"Y":1,"Z":1}
2. {"a._id":1,"b":1,"c":1,"X":1,"d":1,"Y":1,"Z":1}
3. {"m":1,"X":1,"d":1,"Y":1,"Z":1}
4. {"e.numbers":1,"X":1,"d":1,"Y":1,"Z":1}
当我执行给定的执行统计查询时,它会按预期显示SORT_MERGE状态。
以下是解释 -
MongoDB有一个名为equality-sort-range的东西,它告诉我们应该如何创建索引。我只是遵循这条规则并按顺序保留索引。所以索引应该是{Equality fields, "X":1,"d":1,"Y":1,"Z":1, Range fields}
。您可以看到查询的字段范围为" d"只有("d" : { "$lte" : 101 }
)但是" d"已经在索引("X":1,"d":1,"Y":1,"Z":1
)的SORT字段中进行了覆盖,因此我们可以从索引末尾跳过范围部分(即字段" d")。
如果" d"没有处于排序/等式谓词然后我会把它作为范围索引字段的索引,我的索引看起来像{Equality fields, "X":1,"Y":1,"Z":1,"d":1}
。
现在我的索引是{Equality fields, "X":1,"d":1,"Y":1,"Z":1}
,我只关心平等字段。因此,为了找出相等的字段,我只是检查查询查找谓词,我发现有两个条件由OR运算符组合。
"a._id", "b", "c", "m"
上具有相等性(" d"具有范围,而不是相等)。所以我需要创建一个像"a._id":1,"m":1,"b":1,"c":1,"X":1,"d":1,"Y":1,"Z":1
这样的索引,但这会产生错误,因为它有两个数组字段" a_id"和" m"。正如我们所知,Mongo不允许compound index on parallel arrays所以它会失败。所以我创建了两个单独的索引,只允许Mongo使用查询规划器选择的任何内容。因此我创建了第一个和第二个索引。现在我们知道单个查询一次只能使用一个索引,所以我需要创建这些索引,因为我不知道OR运算符的哪个分支将被执行。
注意:如果您担心索引的大小,那么您只能保留前两个索引和前两个索引。或者你也可以保留所有四个和提示mongo使用正确的索引,如果你在查询规划器之前就知道它。