在 Mongoose 中使用 MongoDB Explain 解释查询

发布于 2022-07-13 13:16:50 字数 4924 浏览 233 评论 0

在 MongoDB 中, explaincommand 告诉 MongoDB 服务器返回有关它如何执行查询的统计信息,而不是查询的结果。 Mongoose 查询 有一个 explain() 将查询转换为 explain()

const Character = mongoose.model('Character', mongoose.Schema({
  name: String,
  age: Number,
  rank: String
}));

await Character.create([
  { name: 'Jean-Luc Picard', age: 59, rank: 'Captain' },
  { name: 'William Riker', age: 29, rank: 'Commander' },
  { name: 'Deanna Troi', age: 28, rank: 'Lieutenant Commander' },
  { name: 'Geordi La Forge', age: 29, rank: 'Lieutenant' },
  { name: 'Worf', age: 24, rank: 'Lieutenant' }
]);

const explain = await Character.find({ name: /Picard/ }).explain().
  then(res => res[0]);
// Object describing how MongoDB planned to execute the query
explain.queryPlanner;
// Object containing stats about how MongoDB executed the query
explain.executionStats;

阅读 queryPlanner 输出

queryPlanner对象包含有关 MongoDB 如何决定执行查询的更多详细信息。 例如,下面是 queryPlanner 从上面的对象 explain() 称呼。

{
  plannerVersion: 1,
  namespace: 'test.characters',
  indexFilterSet: false,
  parsedQuery: { name: { '$regex': 'Picard' } },
  winningPlan: {
    stage: 'COLLSCAN',
    filter: { name: { '$regex': 'Picard' } },
    direction: 'forward'
  },
  rejectedPlans: []
}

最重要的信息是 winningPlan属性,它包含有关 MongoDB 决定执行查询的计划的信息。 在实践中, winningPlan对于检查 MongoDB 是否使用索引进行查询很有用。

查询计划 是用于识别与查询匹配的文档的阶段列表 上面的计划只有一个阶段,COLLSCAN,这意味着 MongoDB 执行了一次完整的集合扫描来回答查询。

集合扫描意味着 MongoDB 搜索“字符”集合中的每个文档以查看是否 name匹配给定的查询。 当您引入索引时,查询计划会变得更加复杂。 例如,假设您在 name 如下所示。

await Character.collection.createIndex({ name: 1 });

const explain = await Character.find({ name: 'Jean-Luc Picard' }).explain().
  then(res => res[0]);
// Object describing how MongoDB planned to execute the query
explain.queryPlanner;

queryPlanner 输出如下所示:

{
  plannerVersion: 1,
  namespace: 'test.characters',
  indexFilterSet: false,
  parsedQuery: { name: { '$eq': 'Jean-Luc Picard' } },
  winningPlan: {
    stage: 'FETCH',
    inputStage: {
      stage: 'IXSCAN',
      keyPattern: { name: 1 },
      indexName: 'name_1',
      isMultiKey: false,
      multiKeyPaths: { name: [] },
      isUnique: false,
      isSparse: false,
      isPartial: false,
      indexVersion: 2,
      direction: 'forward',
      indexBounds: { name: [ '["Jean-Luc Picard", "Jean-Luc Picard"]' ] }
    }
  },
  rejectedPlans: []
}

winningPlan 属性是一个递归结构: winningPlan 指向获胜查询计划的最后一个阶段,每个阶段都有一个 inputStage 描述前一阶段的属性。 在上述计划中,有两个阶段:IXSCAN 和FETCH。 这意味着第一个 MongoDB 使用 { name: 1 } 索引来识别哪些文档与查询匹配,然后获取各个文档。

阅读 executionStats输出

executionStats 输出比 queryPlanner:它包括关于每个阶段花费了多长时间以及每个阶段扫描了多少文件的统计信息。

例如,下面是 executionStats 简单集合扫描的输出:

{
  executionSuccess: true,
  nReturned: 1,
  executionTimeMillis: 0,
  totalKeysExamined: 0,
  totalDocsExamined: 5,
  executionStages: {
    stage: 'COLLSCAN',
    filter: { name: { '$regex': 'Picard' } },
    nReturned: 1,
    executionTimeMillisEstimate: 0,
    works: 7,
    advanced: 1,
    needTime: 5,
    needYield: 0,
    saveState: 0,
    restoreState: 0,
    isEOF: 1,
    direction: 'forward',
    docsExamined: 5
  },
  allPlansExecution: []
}

这里要注意的重要细节是顶层 executionTimeMillistotalDocsExamined 特性。 executionTimeMillis 是 MongoDB 执行查询所花费的时间,以及 totalDocsExamined 是 MongoDB 为回答查询而必须查看的文档数量。

请记住, executionTimeMillis包括网络延迟或 花费的时间 。 只是因为 executionTimeMillis 小并不意味着最终用户可以立即看到结果。 当你有一个索引和多个阶段时, executionStats 分解每个阶段的大致执行时间和扫描的文档数量。

下面是 executionStats 对于带有索引的查询,为简洁起见,排除了一些不太重要的细节:

{
  executionSuccess: true,
  nReturned: 1,
  executionTimeMillis: 2,
  totalKeysExamined: 1,
  totalDocsExamined: 1,
  executionStages: {
    stage: 'FETCH',
    nReturned: 1,
    executionTimeMillisEstimate: 0,
    // ...
    docsExamined: 1,
    // ...
    inputStage: {
      stage: 'IXSCAN',
      nReturned: 1,
      executionTimeMillisEstimate: 0,
      // ...
    }
  },
  allPlansExecution: []
}

以上 executionStats 输出表明有两个阶段:IXSCAN 和 FETCH。 IXSCAN 阶段在 0 毫秒内执行并导致一个文档被发送到 FETCH 阶段。 FETCH 阶段检查了 1 个文档,并返回了 1 个文档,这是查询的最终结果。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

荆棘i

暂无简介

0 文章
0 评论
25 人气
更多

推荐作者

已经忘了多久

文章 0 评论 0

15867725375

文章 0 评论 0

LonelySnow

文章 0 评论 0

走过海棠暮

文章 0 评论 0

轻许诺言

文章 0 评论 0

信馬由缰

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文