mongodb查询处理流程

简介: 杨立明 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,在释放的时候,它将被放在空闲链表里面,备后续使用.

目录
相关文章
|
NoSQL 测试技术 MongoDB
微服务——MongoDB实战演练——根据上级ID查询文章评论的分页列表
本节介绍如何根据上级ID查询文章评论的分页列表,主要包括以下内容:(1)在CommentRepository中新增`findByParentid`方法,用于按父ID查询子评论分页列表;(2)在CommentService中新增`findCommentListPageByParentid`方法,封装分页逻辑;(3)提供JUnit测试用例,验证功能正确性;(4)使用Compass插入测试数据并执行测试,展示查询结果。通过这些步骤,实现对评论的高效分页查询。
237 0
|
存储 NoSQL MongoDB
掌握MongoDB索引优化策略:提升查询效率的关键
在数据库性能调优中,索引是提升查询效率的利器。本文将带你深入了解MongoDB索引的内部工作原理,探讨索引对查询性能的影响,并通过实际案例指导如何针对不同的查询模式建立有效的索引。不仅将涵盖单一字段索引,还会探讨复合索引的使用,以及如何通过分析查询模式和执行计划来优化索引,最终实现查询性能的最大化。
|
9月前
|
存储 JSON NoSQL
查询 MongoDB--SPL 轻量级多源混算实践 4
SPL 支持多种数据源连接,包括 MongoDB 等 NoSQL 数据库。通过外部库形式提供驱动,灵活扩展,可实现实时数据计算与混合分析。
|
NoSQL 定位技术 MongoDB
解锁MongoDB索引的秘密:优化查询效率与应对限制的策略
解锁MongoDB索引的秘密:优化查询效率与应对限制的策略
416 0
|
SQL NoSQL Java
Java使用sql查询mongodb
通过MongoDB Atlas Data Lake或Apache Drill,可以在Java中使用SQL语法查询MongoDB数据。这两种方法都需要适当的配置和依赖库的支持。希望本文提供的示例和说明能够帮助开发者实现这一目标。
656 17
|
SQL NoSQL Java
Java使用sql查询mongodb
通过使用 MongoDB Connector for BI 和 JDBC,开发者可以在 Java 中使用 SQL 语法查询 MongoDB 数据库。这种方法对于熟悉 SQL 的团队非常有帮助,能够快速实现对 MongoDB 数据的操作。同时,也需要注意到这种方法的性能和功能限制,根据具体应用场景进行选择和优化。
625 9
|
存储 NoSQL MongoDB
MongoDB 查询分析
10月更文挑战第21天
188 1
|
NoSQL MongoDB 索引
MongoDB 覆盖索引查询
10月更文挑战第21天
181 1
|
SQL NoSQL MongoDB
MongoDB 查询文档
10月更文挑战第15天
739 1
|
JSON NoSQL MongoDB
MongoDB Schema设计实战指南:优化数据结构,提升查询性能与数据一致性
【8月更文挑战第24天】MongoDB是一款领先的NoSQL数据库,其灵活的文档模型突破了传统关系型数据库的限制。它允许自定义数据结构,适应多样化的数据需求。设计MongoDB的Schema时需考虑数据访问模式、一致性需求及性能因素。设计原则强调简洁性、查询优化与合理使用索引。例如,在构建博客系统时,可以通过精心设计文章和用户的集合结构来提高查询效率并确保数据一致性。正确设计能够充分发挥MongoDB的优势,实现高效的数据管理。
694 3

推荐镜像

更多