MongoDB系列之查询计划

概述

一个查询具体如何被执行的过程,称为查询计划。MongoDB采用自底向上的方式来构造查询计划,每一个查询计划(query plan)都会被分解为若干个有层次的阶段(stage)。整个查询计划最终会呈现出一颗多叉树。
在这里插入图片描述
整个计算过程是从下向上投递的,每一个阶段的计算结果都是其上层阶段的输入,每一个阶段都有自己的逻辑语义。

执行模式

explain有3种执行模式:

  • queryPlanner:默认,仅进行查询计划分析,输出计划中的阶段信息。
  • executionStats:执行模式,在查询计划分析后,将按照winningPlan执行查询并统计过程信息。
  • allPlansExecution:全计划执行模式,将执行所有计划(包括winningPlan和rejectPlans),并返回全部的过程统计信息。

根据MongoDB版本不同,explain命令的输出结果包含不同的丰富的信息(字段)。以MongoDB 6.0.5版本为例,执行命令db.game.find().explain();db.game.find().explain('queryPlanner');,输出完全一样:

[{"command": {"find": "game","filter": {},"$db": "test"},"explainVersion": "1","ok": 1,"queryPlanner": {"namespace": "test.game","indexFilterSet": false,"parsedQuery": {},"queryHash": "17830885","planCacheKey": "17830885","maxIndexedOrSolutionsReached": false,"maxIndexedAndSolutionsReached": false,"maxScansToExplodeReached": false,"winningPlan": {"stage": "COLLSCAN","direction": "forward"},"rejectedPlans": []},"serverInfo": {"host": "johnnydeMBP.ada.local","port": 27017,"version": "6.0.5","gitVersion": "c9a99c120371d4d4c52cbb15dac34a36ce8d3b1d"},"serverParameters": {"internalQueryFacetBufferSizeBytes": 104857600,"internalQueryFacetMaxOutputDocSizeBytes": 104857600,"internalLookupStageIntermediateDocumentMaxSizeBytes": 104857600,"internalDocumentSourceGroupMaxMemoryBytes": 104857600,"internalQueryMaxBlockingSortMemoryUsageBytes": 104857600,"internalQueryProhibitBlockingMergeOnMongoS": 0,"internalQueryMaxAddToSetBytes": 104857600,"internalDocumentSourceSetWindowFieldsMaxMemoryBytes": 104857600}}
]

部分字段解读:

  • queryPlanner:描述查询计划
  • queryPlanner.indexFilterSet:是否设置indexFilter,indexFilter可决定查询优化器对于某个查询将如何使用索引
  • serverInfo:MongoDB服务器概要信息
  • serverParameters:参数设置

执行命令db.game.find().explain('executionStats');,输出内容除executionStats字段外,和db.game.find().explain('queryPlanner');完全一致,都出部分:

"executionStats": {"executionSuccess": true,"nReturned": 0,"executionTimeMillis": 0,"totalKeysExamined": 0,"totalDocsExamined": 0,"executionStages": {"stage": "COLLSCAN","nReturned": 0,"executionTimeMillisEstimate": 0,"works": 2,"advanced": 0,"needTime": 1,"needYield": 0,"saveState": 0,"restoreState": 0,"isEOF": 1,"direction": "forward","docsExamined": 0}
}

executionStats:执行过程统计,捕获计划在执行过程中的相关信息,只有在executionStats或allPlansExecution模式下才会输出。

执行命令db.game.find().explain('allPlansExecution');相比于db.game.find().explain('executionStats');,输出结果多一个allPlansExecution字段。

IndexFilter

queryPlanner.winningPlan.stage

queryPlanner.winningPlan.stage参数如下:

类型描述
COLLSCAN全表扫描
IXSCAN索引扫描
FETCH根据索引检索指定的文档
SHARD_MERGE将各个分片的返回结果进行merge
SORT在内存中进行排序
LIMIT使用limit限制返回结果数量
SKIP使用skip进行跳过
IDHACK针对_id字段进行查询
SHANRDING_FILTER通过mongos对分片数据进行查询
COUNT利用db.coll.explain().count()进行count运算
COUNTSCAN不使用index进行count时
COUNT_SCAN使用Index进行count时
SUBPLA未使用到索引的$or查询的stage返回
TEXT使用全文索引进行查询时候的stage返回
PROJECTION限定返回字段时候stage的返回

缓存

一个查询操作可能对应多个不同的查询计划。无论是哪一种方式,都会先经过内部的评分机制进行评估,最终选出一个最优的执行方案。查询计划的评估必然会产生一定的计算开销。

MongoDB提供PlanCache用以实现查询计划缓存能力,可避免在一定条件内对同一个查询模型进行重复性的分析和评估工作。如果对于某个查询已经有了确定性的选择,查询优化器会直接做出选择,此时缓存并不会启用。
在这里插入图片描述
步骤解读:

  • 查询开始执行,判断PlanCache中是否有对应的缓存。
  • 如果没有缓存,则进入计划生成阶段,执行如下步骤:
    • 分析查询语句与全部索引,产生候选计划。
    • 评估查询计划,包括对计划的并发执行、采样。
    • 选择最优的计划。
    • 将计划存入缓存。
  • 如果存在缓存,则触发replanning机制,评估查询性能,此时有两种结果:
    • 查询性能不达标,淘汰缓存重新生成计划。
    • 查询性能达标,采纳计划。
  • 执行最终计划,返回结果。

查询模型(query shape)是对于当前查询场景的唯一性结构描述。查询优化器会首先将查询请求解析为某个查询模型,根据这个模型再进行计划缓存的查询。查询模型的组成包括以下3个部分:

  • query:描述查询条件的结构,该结构由条件的字段、操作符(谓词)以及条件的嵌套关系组成,并不包含查询条件的具体值
  • projection:描述即将返回哪些字段
  • sort:描述排序的规则。

如果同时存在多个候选计划,那么需要根据一种评分机制从这些计划中选出一个最优计划,这就涉及计划的评优(evaluate)过程。

首先,让所有计划都同时执行一定量的扫描任务,扫描任务在满足以下条件时停止:

  • 扫描次数达到numWorks次,numWorks=Math.max(10000, 0.3×collection.count)
  • 返回结果达到numResults个,numResults=Math.min(101, query.getN(), query.getLimit()),其中query.getN()来自getMore命令,query.getLimit()则只有限制limit条件才会出现。这两个参数只有存在时才会参与比较,否则numResults默认就是101。

为每个计划的执行情况打分,计算分数的因子来自下面几点:

  • isEOF是否为true,如果出现isEOE则说明扫描的指针已经到达末尾。如果计划提前结束,则扫描会获得最大的机会。
  • advance/workUnits(%),如果返回的结果数占扫描数的比例越大,则代表扫描效率越高。

是否存在以下低效率的阶段:

  • PROJECTION+FETCH(非覆盖索引查询)
  • SORT(内存排序)
  • AND_HASH|STAGE_AND_SORTED(索引正交阶段)。

任意一种低效阶段的存在都会导致候选计划被扣分。

最后,根据所得分数进行排序,得分最高的计划被评选为最优计划并写入缓存。

对于已经缓存的计划,MongoDB仍会采用一种replaining的机制来保证其高效性。在返回缓存的计划之前,首先对该计划进行扫描采样,这次的采样数相比之前的numWorks会扩大10倍:

  • 扫描过程中如果返回numResults个条目,或者到达EOF,则达到通过(pass)条件,此时仍然选用此计划。
  • 如果超过采样数之后仍未达到通过条件,则转为失败(fail)状态,触发replain过程,此时将重新评选计划。
  • 如果扫描过程中出错,则同样会变成失败状态,此时也会触发replain过程。

触发查询计划缓存清除的时机:

  • 执行PlanCache.clear方法。
  • 创建、删除索引或者执行集合的drop操作。
  • 重启MongoDB进程。

强制命中

在某些极少情况下,某些查询产生的最终计划可能并不是你想要的。事实上,想实现一个完美的查询计划是非常困难的,MongoDB在查询优化器上做了很多合理性方面的努力,如提供一些干预的手段。

hint方法实现对查询计划机制的干预,在查询计划中使用hint语句可以让MongoDB忽略查询优化器的结果,从而直接使用指定的索引。hint方法参数可以传入索引的定义对象,也可以是索引的名称。

IndexFilter方法也可以于预查询索引:

db.runCommand({planCacheSetFilter: "test",query: {a: 3, b: 4},index: [{b: 1}]}
)

执行planCacheSetFilter命令会在test集合中增加一个IndexFilter对象,该对象将会自动关联到同时包含a字段与b字段的等值查询,并引导查询优化器使用{b: 1}这个索引。

IndexFilter的优先级高于hint方法,如果查询优化器发现关联的IndexFilter,则一定会忽略hint语句。但是,IndexFilter并不能保证查询优化器最终一定会选择对应的索引,事实上优化器会将这些索引与全表扫描方式一并进行评估,再抉择出最终的结果。在最坏的情况下,如果指定不存在的索引,就会导致全表扫描。

IndexFilter是内存态的,重启MongoDB则会自动失效。另外,也可以使用planCacheClearFilters进行擦除。

参考

  • MongoDB进阶与实战:微服务整合、性能优化、架构管理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/759405.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ReaLTaiizor开源.NET winform控件库学习使用

一、ReaLTaiizor项目介绍 1.1 介绍及地址 基于MIT license开源、免费、美观的.NET WinForm UI控件库:ReaLTaiizor ReaLTaiizor是一个开源免费的.NET WinForms控件库,它提供了广泛的组件和丰富的主题选项(用户友好、注重设计)&am…

提供数字免疫力:采取整体方法来优化您的网络

采用数字技术已成为许多美国企业的关键竞争优势,导致其在与新部署的云解决方案的安全连接方面的投资不断增加。然而,随着越来越多的关键应用程序迁移到云端,公司保护其敏感数据和资源变得更具挑战性,因为这些资产现在超出了内部防…

C#中Console.WriteLine()函数输出格式详解

格式项都采用如下形式: {index[,alignment][:formatString]} 其中"index"指索引占位符,这个肯定都知道; “,alignment"按字面意思显然是对齐方式,以”,"为标记; “:formatString"就是对输出格式的限…

js读取本地 excel文件、txt文件的内容

<input type"file" change"fileChange"> 1、txt文件 fileChange(event) {console.log(fileChange, event)const file event.target.files[0];const reader new FileReader();reader.readAsText(file);reader.onload function(e) {console.log(r…

基于SpringBoot的学生成绩管理系统

基于SpringBootVue的家教管理系统的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 系统功能结构展示 登录界面图 现今&#xff0c;越来越多的人乐于选择一项合适的管理方案&#xff0c;但是普通用户往往受到管理经验地限制&…

ES 常见面试题及答案

目录 es 写入数据流程 es 删除数据流程 es 读数据流程 es 部署的服务有哪些角色 es 的实现原理 es 和lucence 关系 如何提高写入效率 提高搜索效率 es doc value指的啥 分片指的啥&#xff0c;定义后可不可义再修改 深分页如何优化 对于聚合操作是如何优化的 元数据…

面试九 设计模式

单例模式通常被归类为创建型设计模式&#xff0c;因为它主要关注如何创建对象的实例&#xff0c;以及如何确保在整个应用程序生命周期中只有一个实例存在。 1.为什么日志模块和数据库连接池需要单例模式 使用单例模式来实现数据库连接池主要有以下几个原因&#xff1a; 全局唯…

[自研开源] MyData 数据集成之任务调度模式 v0.7

开源地址&#xff1a;gitee | github 详细介绍&#xff1a;MyData 基于 Web API 的数据集成平台 部署文档&#xff1a;用 Docker 部署 MyData 使用手册&#xff1a;MyData 使用手册 试用体验&#xff1a;http://demo.mydata.work 交流 Q 群&#xff1a;430089673 概述 本…

四、Elasticsearch 进阶

自定义目录 4.1 核心概念4.1.1 索引&#xff08;Index&#xff09;4.1.2 类型&#xff08;Type&#xff09;4.1.3 文档&#xff08;Document&#xff09;4.1.3 字段&#xff08;Field&#xff09;4.1.5 映射&#xff08;Mapping&#xff09;4.1.6 分片&#xff08;Shards&#…

富格林:正视安全平台阻挠亏损

富格林悉知&#xff0c;当前不少投资者都意识到一款正规的平台能够帮助我们阻挠亏损确保安全。因此不少投资者在选择都会参考一些排行榜。但是网上这方面的榜单眼花缭乱&#xff0c;新手投资者可能难以从中挑选到能够帮助我们阻挠亏损确保安全的平台。下面富格林将给大家提供一…

STL_list文档使用介绍与底层代码实现简介

文章目录 list介绍list的使用构造函数&#xff08;constructor&#xff09;迭代器list capacitylist modify&#xff08;修改&#xff09;其他接口函数list迭代器失效问题 list实现基础框架(节点类&#xff09;基础框架&#xff08;迭代器类&#xff09;基础框架&#xff08;链…

docker仓库登录及配置insecure-registries的方法

docker仓库登录及配置insecure-registries的方法 这篇文章主要介绍了docker仓库登录配置insecure-registries的方法,docker客户端如果配置中添加了insecure-registary配置&#xff0c;就不需要在docker 客户端配置上对应证书&#xff0c;如果不配置要在/etc/docker/certs.d/目…

【机器学习300问】39、高斯分布模型如何实现异常检测?

一、异常检测是什么&#xff1f; &#xff08;1&#xff09;举几个例子 ① 信用卡交易异常检测 在信用卡交易数据分析中&#xff0c;如果某个用户的消费习惯通常是小额且本地化消费&#xff0c;那么突然出现一笔大额且跨国的交易就可能被标记为异常。 ② 电机温度异常检测 在电…

常见的几个JVM调优场景

文章目录 调优案例案例1&#xff1a;应对高并发、短生命周期对象的应用案例2&#xff1a;防止频繁Full GC导致延迟案例3&#xff1a;优化服务响应时间&#xff0c;减少停顿时间案例4&#xff1a;监控和诊断内存泄露 一些参数堆内存大小元空间大小垃圾收集器相关参数垃圾收集行为…

spring boot学习第十四篇:使用AOP编程

一、基本介绍 1&#xff0c;什么是 AOP &#xff08;1&#xff09;AOP 为 Aspect Oriented Programming 的缩写&#xff0c;意为&#xff1a;面向切面编程&#xff0c;通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。 &#xff08;2&#xff09;利用 AOP…

流畅的 Python 第二版(GPT 重译)(五)

第九章. 装饰器和闭包 有人对将这个功能命名为“装饰器”的选择提出了一些抱怨。主要的抱怨是该名称与其在 GoF 书中的用法不一致。 名称 decorator 可能更多地归因于其在编译器领域的用法—语法树被遍历并注释。 PEP 318—函数和方法的装饰器 函数装饰器让我们在源代码中“标记…

色环电感的工艺结构原理及选型参数总结

🏡《总目录》 目录 1,概述2,工作原理3,结构特点4,工艺流程4.1,磁芯制备:4.2,线圈绕制:5,选型参数5.1,电感值(L)5.2,电流容量(I)5.3,品质因数(Q)5.4,自谐振频率(SRF)5

windows下常用的DOS命令

DOS&#xff08;Disk Operating System&#xff09;是 Windows 操作系统中的命令行接口&#xff0c;也可以叫命令行窗口。一提到这个&#xff0c;很多初入行计算机的朋友们就是很犯怵&#xff0c;不知所错&#xff0c;好高端&#xff0c;有没有。界面如下&#xff1a; 普通用户…

【小程序开发】出行 API 汇总(一)

ty.outdoor.openOutdoorCyclingNavigation 跳转骑行导航页面 引入 import { openOutdoorCyclingNavigation } from ray-js/ray; 注意&#xff1a;当前功能仅在智慧出行App开通使用&#xff0c;需要在基础库2.15.14及以上版本使用。 参数 Object object 属性类型默认值必填…

分享一些关于在实施面试过程被问到的问题

1&#xff0c;说说你对行业现状和发展趋势的看法 一、行业现状&#xff1a; 技术创新&#xff1a;科技行业在近年来取得了显著的技术突破&#xff0c;包括人工智能、大数据、云计算、物联网等领域的发展。这些技术的创新为各行各业带来了前所未有的变革。竞争激烈&#xff1a;…