网站根目录文件名,wordpress禁用谷歌字体解决加载慢方法,品牌建设有效提升城市竞争力例子,北京如何做网站网页执行器#xff08;ExecProcNode#xff09; 概述ExecProcNode 函数ExecProcNodeFirst 函数PlanState 结构体 声明#xff1a;本文的部分内容参考了他人的文章。在编写过程中#xff0c;我们尊重他人的知识产权和学术成果#xff0c;力求遵循合理使用原则#xff0c;并在适… 执行器ExecProcNode 概述ExecProcNode 函数ExecProcNodeFirst 函数PlanState 结构体 声明本文的部分内容参考了他人的文章。在编写过程中我们尊重他人的知识产权和学术成果力求遵循合理使用原则并在适用的情况下注明引用来源。 本文主要参考了 postgresql-10.1 的开源代码和《OpenGauss数据库源码解析》和《PostgresSQL数据库内核分析》一书 概述 在文章【PostgreSQL内核学习二十二—— 执行器ExecutePlan】中详细介绍了 PostgreSQL 数据库中 ExecutePlan 函数的原理和实现细节强调了它在数据库查询执行机制中的核心作用。文章分析了 ExecutePlan 函数的执行流程包括初始化变量、处理并行执行模式、循环执行查询计划节点直到满足退出条件等步骤。此外还介绍了 ExecProcNode 函数的作用即执行给定计划节点并返回元组。 本文将深入了解 ExecProcNode 的原理和实现细节ExecProcNode 函数是 ExecutePlan 函数流程中的关键部分负责实际执行查询计划树中的各个节点并返回结果元组。ExecutePlan 通过循环调用 ExecProcNode处理查询计划中的每一个节点直到获取到空元组表示没有更多的数据需要处理或者达到了预定的元组处理数量。简而言之ExecProcNode 是连接执行器逻辑与具体计划节点执行结果的桥梁。
ExecProcNode 函数 下面是 ExecProcNode 函数的定义其作用是执行给定的查询计划节点并返回一个新的元组。如果节点的 chgParam 非空表示有些参数改变了这时会先调用 ExecReScan 函数来处理这些变化。然后通过调用节点自身的 ExecProcNode 方法来执行节点并获取元组。这个过程是 PostgreSQL 执行计划操作的核心它确保了在查询执行过程中每个节点根据当前的状态和数据动态地生成结果。函数源码如下所示路径postgresql-10.1\src\include\executor\executor.h
/* ----------------------------------------------------------------* ExecProcNode** Execute the given node to return a(nother) tuple.* ----------------------------------------------------------------*/
#ifndef FRONTEND
static inline TupleTableSlot *
ExecProcNode(PlanState *node) // 执行给定的查询计划节点返回一个元组。
{if (node-chgParam ! NULL) /* something changed? */ExecReScan(node); /* 如果节点的参数有变化重新扫描节点以应对这些变化。*/return node-ExecProcNode(node); // 调用节点自身的ExecProcNode方法执行该节点并返回结果元组。
}
#endif在 PostgreSQL 中node-ExecProcNode 通过函数指针指向具体的执行函数。当一个 PlanState 结构体被初始化时根据不同的节点类型如 SeqScan、Join 等ExecProcNode 指针会被设置为指向相应节点特定的执行函数。这样当调用 node-ExecProcNode(node); 时实际上是调用了与节点类型相匹配的具体执行函数。这种设计允许多态行为即同一接口可以根据不同的节点类型执行不同的操作从而实现了查询计划的灵活执行。
ExecProcNodeFirst 函数 ExecProcNodeFirst 函数是 ExecProcNode 的一个封装器用于在第一次调用具体节点的执行函数之前执行一些一次性的检查。这包括执行栈深度检查以确保不会因为递归调用或深层嵌套查询而超出系统栈空间。此外如果需要它还会将节点的执行函数指针从 ExecProcNode 更改为 ExecProcNodeInstr用于收集执行过程中的性能数据。如果不需要性能数据收集它会直接将执行函数指针指向实际的执行函数 ExecProcNodeReal。这样ExecProcNodeFirst 确保在查询执行过程中相关的性能检查和调整只在第一次执行时发生优化了之后的执行效率。函数源码如下所示路径postgresql-10.1\src\backend\executor\execProcnode.c
static TupleTableSlot *ExecProcNodeFirst(PlanState *node)
{// 在节点第一次执行前执行栈深度检查。因为在某些架构上如x86这并不是一个低成本的操作。// 这个假设是基于ExecProcNode对给定计划节点的调用总是在大致相同的栈深度上进行。check_stack_depth();// 如果需要收集执行信息instrumentation则将执行函数指针改为ExecProcNodeInstr只做性能收集。// 否则我们可以去掉所有的封装器并直接从现在开始让ExecProcNode()调用相应的函数。if (node-instrument)node-ExecProcNode ExecProcNodeInstr;elsenode-ExecProcNode node-ExecProcNodeReal;// 调用当前节点设置的执行函数返回处理的元组。return node-ExecProcNode(node);
}PlanState 结构体 其中PlanState 结构体是 PostgreSQL 查询执行计划中各种节点共享的基础数据结构。在 PostgreSQL 的执行引擎中查询计划被编译成一个由多种类型的节点组成的树结构每个节点类型都有自己特定的作用如处理数据连接、过滤、聚合等操作。PlanState结构体作为所有具体节点类型如 SeqScanState、JoinState 等的公共基础包含了执行查询计划时所需的公共状态信息和控制逻辑。结构体源码如下所示路径postgresql-10.1\src\include\nodes\execnodes.h
typedef struct PlanState
{NodeTag type; // 节点类型标识符用于区分不同的计划节点类型Plan *plan; /* 与此状态关联的Plan节点 */EState *state; /* 执行时各个节点的状态指向整个顶层计划的一个EState实例 */ExecProcNodeMtd ExecProcNode; /* 函数指针用于返回下一个结果元组 */ExecProcNodeMtd ExecProcNodeReal; /* 实际的函数如果ExecProcNode是一个包装函数的话 */Instrumentation *instrument; /* 可选的为此节点提供运行时统计信息 */WorkerInstrumentation *worker_instrument; /* 每个工作器的性能监测数据 *//** 所有Plan类型的公共结构数据。这些到子状态树的链接在相关的计划树中也有对应的链接* 除了subPlan列表在计划树中不存在*/ExprState *qual; /* 布尔条件表达式 */struct PlanState *lefttree; /* 输入计划树可能有多个 */struct PlanState *righttree;List *initPlan; /* 初始化的SubPlanState节点非相关表达式子选择 */List *subPlan; /* 表达式中的SubPlanState节点 *//** 管理参数变化驱动的重新扫描的状态*/Bitmapset *chgParam; /* 已变更参数的ID集合 *//** 大多数节点类型所需的其他运行时状态*/TupleTableSlot *ps_ResultTupleSlot; /* 结果元组的槽 */ExprContext *ps_ExprContext; /* 节点的表达式评估上下文 */ProjectionInfo *ps_ProjInfo; /* 进行元组投影的信息 */
} PlanState;其中ExecProcNodeMtd 是 PostgreSQL 查询执行框架中的一个关键组成部分。这个类型的函数指针用于指向实现了特定逻辑的函数这些函数负责从执行计划的某个节点中获取下一个元组tuple。如果没有更多的元组可供获取这些函数将返回 NULL 或一个空的 TupleTableSlot。这个定义允许不同类型的执行节点如顺序扫描、连接操作等实现各自的元组获取逻辑而这些逻辑可以通过相同的接口被执行器调用。
/* 定义一个函数指针类型ExecProcNodeMtd */
typedef TupleTableSlot *(*ExecProcNodeMtd) (struct PlanState *pstate);TupleTableSlot *(*ExecProcNodeMtd) (struct PlanState *pstate);这是一个函数指针的定义它指向的函数接受一个指向 PlanState 结构体的指针作为参数返回一个指向 TupleTableSlot 的指针。这里的 PlanState 代表查询执行树中的一个节点的状态而 TupleTableSlot 是用于存储和传递元组的数据结构。struct PlanState *pstate函数的参数是一个指向 PlanState 结构的指针表示当前执行节点的状态。PlanState 包含了执行该节点所需要的所有上下文信息如节点的执行计划、子节点的状态、当前节点产生的结果等。TupleTableSlot *函数的返回类型是一个指向 TupleTableSlo t的指针。TupleTableSlot 是 PostgreSQL 中用于表示一个元组数据库行的结构可以看作是查询结果的一个容器。如果函数返回一个非空的 TupleTableSlot则表示获取到了一个元组如果返回 NULL 或一个空的 TupleTableSlot则表示没有更多的元组可供处理。