2.可优化语句的执行
可优化语句的共同特点是它们被查询编译器处理后都会生成査询计划树,这一类语句由执行器(Executor)处理。该模块对外提供了三个接口: ExecutorStart、ExecutorRun 和 ExecutorEnd,其输入是包含査询计划树的数据结构QueryDesc,输出则是相关执行信息或结果数据。如果希望执行某个计划树,仅需构造包含此计划树的QueryDesc,并依次调用ExecutorStart、ExecutorRun、ExecutorEnd 3个过程即能完成相应的处理过程。从我之前的文章跟我一起读postgresql源码(六)——Executor(查询执行模块之——查询执行策略)中可以看到,执行器的三个接口函数都是在Portal的相关函数中调用的,分别负责执行器的初始化、执行和清理工作,Portal在处理时也使用了同样的方式,这样可以把资源分配回收工作与执行过程独立开,能够简化执行过程,更是一种很好的资源管理方式。
执行器对于査询计划树的处理,最终被转换为针对计划树上每一个节点的处理。每种节点表示一种物理代数(Physical Algebra)操作,PostgreSQL会依次对其进行初始化、处理和清理。节点的处理被设计为demand-driven模式,父节点使用子节点提供的数据作为输入,并向其上层节点返回处理结果。实际执行时,从根节点开始处理,每个节点的执行过程会根据需求自动调用子节点的执行过程来获取输入数据(一般为元组),从而层层递归执行,实现整个计划树的遍历执行过程。初始化和清理也采用相同的设计模式,这种设计模式使得节点处理的代码结构简洁统一、语义明确,且实现方式简单有效。
接下来将会对执行器部分的各种原理、实现做进一步的介绍。
2.1处理模式
PostgreSQL中的计划节点被定义为有0~2个输入和一个输出,这是为了在实现中能够对应二叉树结构。所以你知道了:所有的计划节点都被组织为二叉树结构。
每一个计划节点对应于树中的一个节点,下层节点的输出作为上层节点输入。数据(元组)从底层节点向上层节点流动,直至根节点,而根节点的输出即为整个査询的结果。
例如有这么一个查询:
select a.q,b.w,c.e from a join b join c order by a.q limit 1;
那么计划节点可能如下所示(其实说实话你explain一条查询就能看到各个节点直接的关系):
limit
^
|
sort
^
|
join
^^
/ \
join scan
^^
/ \
scan scan
在PostgreSQL的实现中,上层函数通过ExecInitNode、ExecProcNode、ExecEndNode二个接口函数来统一对节点进行初始化、执

本文深入探讨了PostgreSQL中查询执行器的工作原理,包括查询计划树的构建与执行过程、节点初始化与执行流程,以及执行器如何高效地处理查询。
最低0.47元/天 解锁文章
578

被折叠的 条评论
为什么被折叠?



