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…

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

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

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

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

ES 常见面试题及答案

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

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

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

四、Elasticsearch 进阶

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

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

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

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

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

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

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

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

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

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

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

windows下常用的DOS命令

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

【Python爬虫】将某网页中表格里的十六进制颜色值转换成十进制,再生成新表格

【需求】 在 https://www.cnblogs.com/heyang78/p/5712076.html 上有360种颜色及代码,但很遗憾没有十进制的RGB值,使用时需要自己转换一下,此过程依赖网络或计算器,颇为不便。因此,拟设计一爬虫将原有表格内容取出&am…

【Linux】初识进程

目录 操作系统是什么 设计操作系统的目的 操作系统的定位 如何理解管理 管理的本质 管理的例子 计算机的管理概念图 操作系统管理逻辑的六字真言 系统调用和库函数的概念 进程 进程的概念 什么是PCB? PCB的主要内容 如何查看进程? 通过系统…

NO9 蓝桥杯单片机实践之串口通信的使用

1 回顾 串口通信的代码编写结构还是与中断一样,不同的是: 初始中断函数条件涉及到串口通信相关的寄存器和定时器1相关的寄存器(定时器1用于产生波特率),但初始条件中的中断寄存器只考虑串口通信而不考虑定时器1。 vo…

CMake笔记之将任意官方库作为third_party完整地包含在工程项目中使用的通用模板

CMake笔记之将任意官方库作为third_party完整地包含在工程项目中使用的通用模板 —— 杭州 2024-03-20 凌晨1:06 code review! 文章目录 CMake笔记之将任意官方库作为third_party完整地包含在工程项目中使用的通用模板1.通用CMakeLists.txt模板2.GPT4给出的改进建议3.git clon…

华为综合案例-普通WLAN全覆盖配置(2)

组网图 结果验证 在AC_1和AC_2上执行display ap all命令,检查当前AP的状态,显示以下信息表示AP上线成功。[AC_1] display ap all Total AP information: nor : normal [1] ExtraInfo : Extra information P : insufficient power supply ---…

wireshark抓tcp包使用指南

本博文源于笔者不断探索加上去网络总结获得的经验,撰写wireshark如何抓tcp包 文章目录 1、打开wireshark2、选择网络源3、搜索ip地址与tcp条件4、看灰色的条纹 1、打开wireshark 2、选择网络源 选择自己当前的ip地址适用于的网络源,比如这里选择“以太…

ideaSSM 高校公寓交流员管理系统bootstrap开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 idea 开发 SSM 高校公寓交流管理系统是一套完善的信息管理系统,结合SSM框架和bootstrap完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完整的源代码和数据库&…

get_local_ip.bat:快速获取IPv4地址

批处理脚本,用于在Windows命令提示符下获取本地计算机的IPv4地址。 echo off ipconfig | findstr IPv4 pause - echo off:这会关闭命令提示符窗口中的命令回显,使得在运行脚本时不会显示每条命令的执行结果。 - ipconfig:这是一…