gpt4 book ai didi

具有复杂查询的 MongoDB 索引覆盖率

转载 作者:行者123 更新时间:2023-12-04 17:24:26 25 4
gpt4 key购买 nike

Mongo 数据库版本 3.4.6

我有一个文档结构类似于以下内容的集合:

{
organization: "ABC123",
tags: ["MARTHA WASHINGTON", "+15552082000"],
updatedAt : ISODate("2020-10-09T17:19:44.861Z"),
createdAt : ISODate("2020-01-14T19:46:15.957Z"),
}

我需要能够按组织进行查询,并在标签数组上使用“开头为”的正则表达式,并可选择按 updatedAt 或 createdAt 进行排序。为此,我创建了以下索引:

{
"organization" : 1,
"tags" : 1,
"createdAt" : -1
}

这是一个多键复合索引,根据我对 Mongo 的理解,它应该允许我涵盖所有情况下的查询。如果我执行如下查询:

db.getCollection('data').find({"organization": "ABC123", "search": /^MARTHA WASHINGTO/})

查询包含在索引中 - 我看到一个 FETCH/IXSCAN 阶段。

同样,如果我删除正则表达式查询并添加排序 - 查询将被完美覆盖。

db.getCollection('data').find({"organization": "ABC123", "search": "MARTHA WASHINGTON"}).sort({"createdAt":-1})

但是,如果我组合正则表达式和排序选项,我突然会在查询中看到一个额外的 SORT 阶段。示例查询:

db.getCollection('data').find({"organization": "ABC123", "search": /^MARTHA WASHINGTO/}).sort({"createdAt":-1})

这是解释的获胜计划输出:

"winningPlan" : {
"stage" : "SORT",
"sortPattern" : {
"createdAt" : -1.0
},
"inputStage" : {
"stage" : "SORT_KEY_GENERATOR",
"inputStage" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"organization" : 1,
"tags" : 1,
"createdAt" : -1
},
"indexName" : "tag matches by organization",
"isMultiKey" : true,
"multiKeyPaths" : {
"organization" : [],
"search" : [
"search"
],
"createdAt" : []
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"organization" : [
"[\"ABC123\", \"ABC123\"]"
],
"tags" : [
"[\"MARTHA WASHINGTON\", \"MARTHA WASHINGTOO\")",
"[/^MARTHA WASHINGTON/, /^MARTHA WASHINGTON/]"
],
"createdAt" : [
"[MaxKey, MinKey]"
]
}
}
}
}
},

我很困惑为什么这个查询组合没有被索引覆盖。我的理解是,开始时额外的排序阶段会导致大型集合的性能下降。谁能提供一些指导?我错过了一些限制吗?

更新:移除正则表达式查询时的获胜方案

   "winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"organization" : 1,
"search" : 1,
"createdAt" : -1
},
"indexName" : "tag matches by organization",
"isMultiKey" : true,
"multiKeyPaths" : {
"organization" : [],
"search" : [
"search"
],
"createdAt" : []
},
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"organization" : [
"[\"ABC123\", \"ABC123\"]"
],
"tags" : [
"[\"MARTHA WASHINGTON\", \"MARTHA WASHINGTON\"]"
],
"createdAt" : [
"[MaxKey, MinKey]"
]
}
}
},

最佳答案

另一个答案不太准确。来自docs

For case sensitive regular expression queries, if an index exists for the field, then MongoDB matches the regular expression against the values in the index, which can be faster than a collection scan.

Mongo 能够使用带正则表达式的索引,显然,如果您的正则表达式是后缀正则表达式,那么集合扫描实际上可能更快,因为 Mongo 必须读取整个索引树才能满足需求。

那么您的查询中发生了什么?为什么获胜的计划是 sort?好吧,虽然它实际上可能是获取结果的最佳方式,但也有可能 Mongo 只是选择了错误的计划。

首先让我们了解 Mongo 如何选择获胜计划,计划评估是基于比较给定查询的候选计划,看看哪个返回第一批结果(默认为 101 个文档),总体“工作量”最少.工作分数代表查询阶段(索引键比较、获取文档等)中涉及的不同工作。如果多个计划在评估期间执行相同的工作,则有一些小的打破平局的奖金可以帮助选择一个计划来缓存。基本上 Mongo 会进行一场小型“比赛”并等待谁获胜。

因此,在您的情况下,由于具有索引的正则表达式性质,sort 阶段获胜,如果您完全运行计划而不是小样本,则可能会选择不同的计划。

我建议您使用 hint 进行自己的测试,这会强制 Mongo 使用某个索引,这意味着您可以强制 Mongo 为您的查询制定获胜计划。我个人认为(显然依赖于特定的正则表达式)您可以通过这样做来提高性能,因为首先排序几乎不是每一个“最佳”计划。

关于具有复杂查询的 MongoDB 索引覆盖率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64285321/

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