gpt4 book ai didi

MongoDB 多键复合索引 - 需要帮助了解边界

转载 作者:IT老高 更新时间:2023-10-28 13:29:13 30 4
gpt4 key购买 nike

我们最近决定重新审视我们的一些 MongoDB 索引,并在使用包含多键部分的复合索引时遇到了一个特殊的结果。

请务必注意,我们使用的是 v2.4.5

TLDR:当使用具有多键部分的复合索引时,用于范围限制的非多键字段的边界被删除。

我会用一个例子来解释这个问题:

创建一些数据

db.demo.insert(
[{ "foo" : 1, "attr" : [ { "name" : "a" }, { "name" : "b" }, { "name" : "c" } ]},
{ "foo" : 2, "attr" : [ { "name" : "b" }, { "name" : "c" }, { "name" : "d" } ]},
{ "foo" : 3, "attr" : [ { "name" : "c" }, { "name" : "d" }, { "name" : "e" } ]},
{ "foo" : 4, "attr" : [ { "name" : "d" }, { "name" : "e" }, { "name" : "f" } ]}])

索引

db.demo.ensureIndex({'attr.name': 1, 'foo': 1})

查询和解释

查询 'attr.name' 但限制非多键字段 'foo' 的范围:

db.demo.find({foo: {$lt:3, $gt: 1}, 'attr.name': 'c'}).hint('attr.name_1_foo_1').explain()
{
"cursor" : "BtreeCursor attr.name_1_foo_1",
"isMultiKey" : true,
"n" : 1,
"nscannedObjects" : 2,
"nscanned" : 2,
"nscannedObjectsAllPlans" : 2,
"nscannedAllPlans" : 2,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"attr.name" : [
[
"c",
"c"
]
],
"foo" : [
[
-1.7976931348623157e+308,
3
]
]
}
}

如您所见,'foo' 的范围与查询中定义的不一样,一端被完全忽略,导致 nscanned 大于应有的范围。

改变范围操作数的顺序将改变丢弃端:

db.demo.find({foo: {$gt: 1, $lt:3}, 'attr.name': 'c'}).hint('attr.name_1_foo_1').explain()
{
"cursor" : "BtreeCursor attr.name_1_foo_1",
"isMultiKey" : true,
"n" : 1,
"nscannedObjects" : 2,
"nscanned" : 2,
"nscannedObjectsAllPlans" : 2,
"nscannedAllPlans" : 2,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"attr.name" : [
[
"c",
"c"
]
],
"foo" : [
[
1,
1.7976931348623157e+308
]
]
}
}

我们要么错过了一些多键索引基础知识,要么面临一个错误。

我们讨论过类似的主题,包括:

不幸的是,这些帖子解决了在多键值上设置范围的不同用例。

我们尝试做的其他事情:

  • 更改复合索引排序,从非多键字段开始。

  • 将 'foo' 值放入 'attr' 数组中的每个子文档中,按 ('attr.name', 'attr.foo') 索引并在 'attr' 上使用 $elemMatch 'foo' 的范围限制。

  • 在定义范围时使用 $and 运算符:

    db.demo.find({'attr.name': 'c', $and: [{num: {$lt: 3}}, {num: {$gt: 1}}]})
  • 使用 MongoDB v2.5.4

以上都没有任何影响(v2.5.4 通过完全倾倒范围的两端使事情变得更糟)。

我们将不胜感激任何形式的帮助!

非常感谢,

投资返回率

最佳答案

对于其中一个索引字段是数组的复合索引,MongoDB 将仅使用范围查询的下限或上限,以确保返回正确的匹配项。见 SERVER-958例如,限制索引上限和下限都找不到预期的文档。

如果您的范围查询是在数组字段上,您可能会使用 $elemMatch运算符在预期的索引范围内优化您的查询。在 MongoDB 2.4 中,$elemMatch 运算符不适用于非数组字段,因此很遗憾,这对您的用例没有帮助。您可以观看/点赞SERVER-6050: Consider allowing $elemMatch applied to non arrays在 MongoDB 问题跟踪器中。

还有一个 Unresolved 问题 SERVER-7959: Potentially unexpected scans with compound indexes when some fields are multikey描述这种行为。

关于MongoDB 多键复合索引 - 需要帮助了解边界,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20763074/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com