mongodb查询处理流程

本文涉及的产品
云数据库 MongoDB,通用型 2核4GB
简介: 杨立明 2017-9-13 MyMessageHandler 用于处理客户端的发送的请求消息,如CRUD操作,db命令等. process函数是入口函数,函数主要执行做三件事 1 生成执行的上下文环境OperationContext 2 在1)的上下文环境上,处理这个请求消息 3 应答消息 生成.
MyMessageHandler
用于处理客户端的发送的请求消息,如CRUD操作,db命令等.
process函数是入口函数,函数主要执行做三件事
1 生成执行的上下文环境OperationContext
2 在1)的上下文环境上,处理这个请求消息
3 应答消息
生成执行环境
globalServiceContext
这是一个ServiceContext类型的 全局变量,ServiceContext是一个抽象类,有几种类型的子类 ServiceContextMongoD,ServiceContextNoop类,这里我们用到的是ServiceContextMongoD类.此 类用于初始化mongod的一些全局环境,
1 包括初始化存储引擎,因为monogdb支持多存储引擎,所以这里会初始化当前支持的存储引擎
2 为每个客户端生成执行上下文OperationContext
OperationContext
这是一个操作的执行上下文,每个客户端连接Client在执行一个操作的时候,都会生成一个上下文,OperationContext是一个基类,这里会创建一个OperationContextImpl类型的子类.这个类的主要作用有
1 关联当前客户端
2 获取一个新的操作Id
3 通过globalServiceContext得到当前使用的存储引擎
4 根据存储引擎类型,初始化成员变量_recovery,_recovery是RecoveryUnit类型的抽象类,这对应的子类是WiredTigerRecoveryUnit类型.
5 将当前客户端Client的执行上下文设置为自己
RecoveryUnit
这个类是负责将数据持久化,个人理解,所有对数据修改的操作,都将保存到这个类里面,最终一并提交或者回滚.WiredTigerRecoveryUnit类型是针对wiredtiger存储引擎的,主要封装了
1 存储引擎的session分配
2 接收所以这个操作相关的数据变更
3 开始一次事务
4 提交或者回滚一次事务
处理本次请求
assembleResponse
assembleResponse函数是处理本次请求的入口,这里处理所有类型的请求,我们以查询为例进行说明,它的处理流程
1 解析请求类型
2 记录操作日志
3 递增本次操作类型的数量
4 进入receivedCommand处理函数
receivedCommand
处理command类型的消息
1 初始化CurOp的一些成员对象
2 进入runCommands函数
runCommands
根据request消息类型查询这个command的类型,然后执行这个command.
1 调用Command::findCommand查找这个Command类型,实例化这个Command,Command也是一个基类,子类在初始化的时 候,会把command的名字写到Command的_commands成员变量里面,这是个静态变量.如果没有找到command则报错返回,否则返回这 个command类型,我们这里返回FindCmd类型.
2 然后调用Command::execCommand函数去执行FindCmd命令.
Command::execCommand
1 首先调用_checkAuthorization做了些权限校验工作.
2 如果是副本集,要校验发送的消息是否能在对应实例上执行,实例状态要正确,master才能写,slaveOK才能读等.
3 调用FindCmd的run方法
FindCmd::run
1 通过LiteParsedQuery类解析所有语法关键字.
2 通过MatchExpressionParser类的_parse函数解析LiteParsedQuery的filter成员,filter语法上可以形成树结构,所以最终解析出的表达式将会形成表达式树,每个节点是不同的表达式类型.
3 通过CanonicalQuery类的canonicalize函数进一步优化表达式树.
4 通过getExecutorFind函数,得到PlanExecutor.
5 循环调用PlanExecutor的getNext函数获得查询结果.
6 当取得的结果集满足一次返回的数量,将退出循环.
7 如果有剩下的记录还没有取完,则保存游标cursorId,后续会调用getMore记录遍历游标.
8 返回结果集合和cursorId.
getExecutorFind
根据CanonicalQuery得到的表达式树,调用getExecutor得到最终的PlanExecutor
1 调用prepareExecution函数通过CanonicalQuery类得到的表达式树得到大于等于一个查询计划和
2 调用PlanExecutor::make选择最有的PlanExecutor
prepareExecution
用于生成执行QuerySolution和PlanStage.
1 调用QueryPlanner::plan生成查询计划,这将会生成一个或者多个查询计划QuerySolution.
2 调用StageBuilder::build函数,根据查询计划生成计划阶段PlanStage,每个查询计划对应一个计划阶段.
PlanExecutor::make
它初始化PlanExecutor类型,并且调用pickBestPlan选取最优的Plan.里面包含了很多不同类型的PlanStage
PlanExecutor::getNext
PlanExecutor的getNext函数里面调用getNextImpl函数,getNextImpl里面调用了PlanStage的work函数.
CollectionScan::work
我们以如下explain为例,来说明PlanStage的工作.
mgset-4049517113:PRIMARY> db.test.find({item:"card"}).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.test",
"indexFilterSet" : false,
"parsedQuery" : {
"item" : {
"$eq" : "card"
}
},
"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"item" : {
"$eq" : "card"
}
},
"direction" : "forward"
},
"rejectedPlans" : [ ]
},
"serverInfo" : {
"host" : "127.0.0.1",
"port" : 27017,
"version" : "3.2.9",
"gitVersion" : "22ec9e93b40c85fc7cae7d56e7d6a02fd811088c"
},
"ok" : 1
}
1 首先需要初始化CollectionScan的游标_cursor成员变量
2 _cursor是调用Collection的getCursor函数得到的游标
3 然后调用_cursor的seekExact函数得到一条记录,将记录的_id字段记录到_lastSeenId成员变量,以便下次从这个记录之后取值,对于wiredtiger引擎直接调用_cursor->next()获取下一个值.
4 在WorkingSet集合中找到一个可用的位置来存放这条记录,WorkingSetMember的loc字段为记录的id字段,obj字段记录的bson文档,_state字段这里设置为WorkingSetMember::LOC_AND_OBJ.
5 最后调用returnIfMatches,查看这条全表扫描的记录是否符合我们的CollectionScan这个PlanStage的filter.如果符合则返回给PlanExecutor的getNext函数,否则继续往后遍历.
WorkingSet
工作集是用来保存从存储引擎返回的结 果,WorkingSet会保存一次查询的所有PlanStage的结果.它有一个数组成员_data,这个数组用于形成一个链表结构,每个节点是 MemberHolder类型用于保存一条记录和链表的下一个节点的位置,记录将被做一些调整存放在WorkingSetMember类型中.在一次查询 过程中需要很多次的申请与释放MemberHolder,在释放的时候,它将被放在空闲链表里面,备后续使用.

相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。   相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
目录
相关文章
|
7月前
|
JSON NoSQL MongoDB
mongodb基本操作,增删改查,查询,索引,权限机制
mongodb基本操作,增删改查,查询,索引,权限机制
|
7月前
|
SQL NoSQL 关系型数据库
MongoDB复杂分组聚合查询1
MongoDB复杂分组聚合查询1
417 0
|
6月前
|
NoSQL MongoDB 索引
开心档-软件开发入门之MongoDB 覆盖索引查询
开心档-软件开发入门之MongoDB 覆盖索引查询
45 0
|
3月前
|
NoSQL 关系型数据库 MySQL
深入了解 Python MongoDB 查询:find 和 find_one 方法完全解析
在 MongoDB 中,我们使用 find() 和 find_one() 方法来在集合中查找数据,就像在MySQL数据库中使用 SELECT 语句来在表中查找数据一样
65 1
|
18天前
|
JSON NoSQL MongoDB
mongodb导出聚合查询的数据
mongodb导出聚合查询的数据
|
3月前
|
存储 NoSQL 安全
go 连接mongodb执行查询的代码
在Go语言中,你可以使用官方的MongoDB驱动程序 `"go.mongodb.org/mongo-driver/mongo"` 来连接MongoDB并执行查询。以下是一个简单的示例代码,演示如何连接MongoDB并执行查询: 首先,确保你已经安装了MongoDB驱动程序: ```bash go get go.mongodb.org/mongo-driver/mongo ``` 然后,可以使用以下示例代码: ```go package main import ( "context" "fmt" "log" "time" "go.mongodb.org/mongo-driv
|
9月前
|
SQL NoSQL 数据可视化
【国庆弯道超车系列】MongoDB进阶之查询(一)
【国庆弯道超车系列】MongoDB进阶之查询(一)
90 0
|
4月前
|
缓存 NoSQL MongoDB
MongoDB数据库查询性能提高40倍?
MongoDB数据库查询性能提高40倍?
98 0
|
4月前
|
NoSQL JavaScript 前端开发
MongoDB【CRUD练习-条件查询-文档关系】
MongoDB【CRUD练习-条件查询-文档关系】
|
5月前
|
JSON NoSQL MongoDB
MongoDB数据库查询性能提高40倍
MongoDB数据库查询性能提高40倍
MongoDB数据库查询性能提高40倍