对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。
See how MongoDB 9.0 delivers up to 2x higher throughput.
MongoDB Branding Shape
Register now >
Docs 菜单

解释“解释计划结果”

您可以使用解释结果,确定有关查询的以下信息:

  • 完成查询所需的时间

  • 查询是否使用索引

  • 为完成查询而扫描的文档和索引键的数量

注意

查询的解释计划结果可能会在各个 MongoDB 版本之间发生变化。

cursor.explain("executionStats") 和 db.collection.explain("executionStats") 方法提供了有关查询性能的统计信息。这些统计信息可用于衡量查询是否索引以及是如何使用该索引的。有关详细信息,请参阅 db.collection.explain()。

MongoDB Compass提供了“解释计划”模式,可显示有关查询性能的统计信息。这些统计信息可用于衡量查询是否以及如何使用索引。

本页上的示例使用 sample_mflix 数据集中的数据。有关如何将此数据集加载到自管理MongoDB 部署中的详细信息,请参阅加载样本数据集。如果对示例数据库进行了任何修改,则可能需要删除并重新创建数据库才能运行本页上的示例。

本页上的示例使用 sample_mflix示例数据集中的数据。有关如何将此数据集加载到部署的详细信息,请参阅将样本数据导入到Atlas部署中。

加载数据集后,将MongoDB Compass连接到同一部署并打开 movies集合。

集合文档在MongoDB Compass中显示如下:

Compass列出电影集合中的文档
点击放大

以下查询检索 year 字段的值在 2000 和 2005(含)之间的文档:

db.movies.find( { year: { $gte: 2000, $lte: 2005 } } )

此查询与集合中 21349 份文档的 3809 份匹配。

要查看选定的查询计划,请将 cursor.explain("executionStats") 游标方法链接到 find 命令的末尾:

db.movies.find(
{ year: { $gte: 2000, $lte: 2005 } }
).explain("executionStats")
{
queryPlanner: {
namespace: 'sample_mflix.movies',
winningPlan: {
stage: 'COLLSCAN',
'...': '...'
},
'...': '...'
},
executionStats: {
executionSuccess: true,
nReturned: 3809,
totalKeysExamined: 0,
totalDocsExamined: 21349,
executionStages: {
stage: 'COLLSCAN',
'...': '...'
},
'...': '...'
},
'...': '...'
}

以下查询检索 year 字段的值在 2000 和 2005(含)之间的文档:

将以下过滤器复制到 Compass 查询栏中,然后单击 Find:

{ year: { $gte: 2000, $lte: 2005 } }

此查询与集合中 21349 份文档的 3809 份匹配。

要查看查询计划,请单击查询栏中的 Explain。

MongoDB Compass 显示查询计划,如下所示:

电影集合的Compass无索引查询计划
点击放大
  • Query Performance Summary 显示查询的执行统计信息:

    • Documents Returned 显示 3809 以表明获胜的查询计划返回 3,809 文档。

    • Documents Examined 显示 21349 以指示MongoDB必须扫描集合中的所有 21,349 文档才能找到 3,809 匹配文档。

    • Index Keys Examined 显示 0 表明该查询未使用索引。

  • MongoDB Compass显示 COLLSCAN查询阶段,表示此查询使用了集合扫描。集合扫描表明 mongod 必须逐个文档扫描整个集合文档才能识别结果。这通常是一项成本高昂的操作,可能会导致查询速度减慢。

还可以通过单击 Raw Output 选项以原始JSON格式查看 Explain Plan 详细信息:

Compass无索引查询计划原始JSON
点击放大

匹配文档和已检查文档之间的数量差异可能表明,使用索引可能有助于提高查询效率。

要支持对 year 字段的查询,请对 year 字段添加索引:

db.movies.createIndex( { year: 1 } )

要查看查询计划的统计信息,请使用 explain() 方法:

db.movies.find(
{ year: { $gte: 2000, $lte: 2005 } }
).explain("executionStats")
{
queryPlanner: {
namespace: 'sample_mflix.movies',
winningPlan: {
stage: 'FETCH',
inputStage: {
stage: 'IXSCAN',
keyPattern: {
year: 1
},
'...': '...'
},
'...': '...'
},
'...': '...'
},
executionStats: {
executionSuccess: true,
nReturned: 3809,
totalKeysExamined: 3809,
totalDocsExamined: 3809,
'...': '...'
},
'...': '...'
}

要支持对 year 字段的查询,请对 year 字段添加索引:

  1. 单击sample_mflix.movies集合的Indexes标签页。

  2. 单击 Create,然后从下拉菜单中选择 Index。

  3. 从 Select or type a field name 下拉列表中选择 year。

  4. 从 Select a type 下拉列表中选择 1 (asc)。

  5. 单击 Create Index(连接)。

注意

将索引名称字段留空会导致 MongoDB Compass 为索引创建默认名称。

现在,您可以在 Indexes 标签页中看到新创建的索引:

Compass在“索引”标签标签页中显示年份索引
点击放大

返回到 sample_mflix.movies 集合的 Documents 标签页,然后重新运行上一步中的查询:

{ year: { $gte: 2000, $lte: 2005 } }

打开 Explain Plan 模态窗口。 MongoDB Compass 显示查询计划,如下所示:

Compass使用年份索引解释计划
点击放大
  • Query Performance Summary 显示查询的执行统计信息:

    • Documents Returned 显示 3809 以表明获胜的查询计划返回 3,809 文档。

    • Documents Examined 显示 3809 以表明MongoDB已扫描 3、809 文档。

    • Index Keys Examined 显示 3809 表示MongoDB已扫描 3,809索引项。检查的键数量与返回的文档数量相匹配,这意味着 mongod 只需要检查索引键即可返回结果。 mongod 不必扫描所有文档,只需将 3,809 匹配的文档拉入内存。这样查询就非常高效。

    • 在 Query Performance Summary 的底部, MongoDB Compass显示该查询使用了 year索引。

  • 在 Query Performance Summary 的左侧, MongoDB Compass显示查询阶段 FETCH 和 IXSCAN。 IXSCAN 表示 mongod 在执行 FETCH 阶段并检索文档之前使用索引来满足查询。

还可以通过单击 Raw Output 选项以原始JSON格式查看解释详细信息:

Compass使用年份索引原始JSON解释计划
点击放大

如果没有索引,查询将扫描整个集合以返回匹配的文档。查询还必须扫描每个文档的整体,可能会将它们拉入内存。这会导致查询操作成本高昂且可能缓慢。

使用索引运行时,查询仅扫描返回的索引项和文档,从而提高查询效率。

比较索引性能

如要手动比较使用多个索引的查询性能,您可以结合使用 hint() 方法和 explain() 方法。

考虑以下查询:

db.movies.find( {
year: {
$gte: 2000, $lte: 2005
},
rated: "PG"
} )

此查询匹配 235 文档。

为支持查询,请添加复合索引。在复合索引中,字段的顺序很重要。

例如,添加以下两个复合索引。第一个索引首先按 year 字段排序,然后按 rated 字段排序。第二个索引首先按 rated 排序,然后按 year 字段排序。

db.movies.createIndex( { year: 1, rated: 1 } )
db.movies.createIndex( { rated: 1, year: 1 } )

评估第一个索引对查询的影响:

db.movies.find(
{ year: { $gte: 2000, $lte: 2005 }, rated: "PG" }
).hint( { year: 1, rated: 1 } ).explain("executionStats")
{
queryPlanner: {
namespace: 'sample_mflix.movies',
winningPlan: {
stage: 'FETCH',
inputStage: {
stage: 'IXSCAN',
keyPattern: {
year: 1,
rated: 1
},
'...': '...'
},
'...': '...'
},
'...': '...'
},
executionStats: {
executionSuccess: true,
nReturned: 235,
totalKeysExamined: 246,
totalDocsExamined: 235,
'...': '...'
},
'...': '...'
}

MongoDB扫描了246个索引键 (executionStats.totalKeysExamined) 以返回 235 个匹配的文档 (executionStats.nReturned)。

评估第二个索引对查询的影响:

db.movies.find(
{ year: { $gte: 2000, $lte: 2005 }, rated: "PG" }
).hint( { rated: 1, year: 1 } ).explain("executionStats")
{
queryPlanner: {
namespace: 'sample_mflix.movies',
winningPlan: {
stage: 'FETCH',
inputStage: {
stage: 'IXSCAN',
keyPattern: {
rated: 1,
year: 1
},
'...': '...'
},
'...': '...'
},
'...': '...'
},
executionStats: {
executionSuccess: true,
nReturned: 235,
totalKeysExamined: 235,
totalDocsExamined: 235,
'...': '...'
},
'...': '...'
}

MongoDB扫描了235个索引键 (executionStats.totalKeysExamined) 以返回 235 个匹配的文档 (executionStats.nReturned)。

因此,第二个复合索引{ rated: 1, year: 1 } 是支持示例查询的更有效索引,因为MongoDB服务器只需扫描 235 index keys 即可使用此索引查找所有匹配的文档,而 246 则使用此索引使用复合索引{ year: 1, rated: 1 }。

给本页内容打分

在此页面上