【PostgreSQL内核学习(二十三)—— 执行器(ExecEndPlan)】

这篇具有很好参考价值的文章主要介绍了【PostgreSQL内核学习(二十三)—— 执行器(ExecEndPlan)】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

声明:本文的部分内容参考了他人的文章。在编写过程中,我们尊重他人的知识产权和学术成果,力求遵循合理使用原则,并在适用的情况下注明引用来源。
本文主要参考了 postgresql-10.1 的开源代码和《OpenGauss数据库源码解析》和《PostgresSQL数据库内核分析》一书

概述

  在这三篇文章中,首先是【OpenGauss源码学习 —— 执行器(execMain)】,它详细探讨了 OpenGauss 数据库管理系统中执行器模块的主要功能和实现机制。这部分内容涉及到如何在 OpenGauss 环境下处理和执行 SQL 语句,包括查询计划生成和优化,以及如何有效地管理数据流和处理结果
  接着,【PostgreSQL内核学习(二十一)—— 执行器(InitPlan)】专注于 PostgreSQL 数据库的执行器模块,特别是初始化计划(InitPlan)的部分。这篇文章讨论了在执行查询之前,如何准备和设置执行环境,包括加载必要的数据结构、分配资源等。这是理解 PostgreSQL 查询处理的关键部分,涉及到数据库内核的深层次工作机制。
  最后,【PostgreSQL内核学习(二十二)—— 执行器(ExecutePlan)】则是关于 PostgreSQL 执行器中执行计划ExecutePlan)的详细分析。这部分内容深入探讨了如何将初始化阶段准备好的计划转化为实际的操作,执行具体的查询。它包括了查询的执行流程,以及如何处理和优化各种数据库操作
  简单总结,这三篇文章都集中在数据库管理系统中的执行器模块,讲述了从初始化计划到执行计划的整个过程。通过深入分析 OpenGaussPostgreSQL 中的实现细节,这些文章为理解优化数据库查询处理提供了宝贵的视角。对数据库开发者和研究者来说,这些内容无疑是非常有价值的资源。
  本文最后将深入了解 ExecEndPlan原理实现细节,从而更好地理解数据库查询的执行机制。具体学习的模块如下图红色框体所示:
【PostgreSQL内核学习(二十三)—— 执行器(ExecEndPlan)】,PostgerSQL,postgresql,数据库

ExecEndPlan 函数

  ExecEndPlan 函数的功能是结束查询计划的执行,主要负责清理和释放在查询执行过程中创建和占用的资源。这包括关闭特定节点类型的查询处理处理子计划销毁执行器的元组表(同时释放缓冲区引脚和元组描述符的引用计数),关闭结果关系相关的索引,以及处理触发器状态和行标记。代码的主要目的是确保所有打开的文件和资源得到适当的关闭和释放,以维护系统的稳定性和效率。函数源码如下所示:(路径:src\backend\executor\execMain.c

/* ----------------------------------------------------------------
 *      ExecEndPlan
 *
 *      清理查询计划 —— 关闭文件并释放存储
 *
 * 注意:现在不太需要担心这段代码中的存储释放;
 * FreeExecutorState应该保证释放所有需要释放的内存。我们关心的是
 * 关闭关联关系和丢弃缓冲区引脚。因此,元组表必须被清空或丢弃以确保引脚被释放。
 * ----------------------------------------------------------------
 */
static void
ExecEndPlan(PlanState *planstate, EState *estate)
{
    ResultRelInfo *resultRelInfo;
    int i;
    ListCell *l;

    /*
     * 关闭节点类型特定的查询处理
     */
    ExecEndNode(planstate);

    /*
     * 同样处理子计划
     */
    foreach(l, estate->es_subplanstates)
    {
        PlanState *subplanstate = (PlanState *) lfirst(l);

        ExecEndNode(subplanstate);
    }

    /*
     * 销毁执行器的元组表。实际上我们只关心释放缓冲区引脚和元组描述符的引用计数;
     * 没有必要释放TupleTableSlots,因为包含它们的内存上下文马上就会消失。
     */
    ExecResetTupleTable(estate->es_tupleTable, false);

    /*
     * 如果有的话,关闭结果关系,但在事务提交前保持锁定。
     */
    resultRelInfo = estate->es_result_relations;
    for (i = estate->es_num_result_relations; i > 0; i--)
    {
        /* 先关闭索引,然后关闭关系本身 */
        ExecCloseIndices(resultRelInfo);
        heap_close(resultRelInfo->ri_RelationDesc, NoLock);
        resultRelInfo++;
    }

    /* 关闭根目标关系。 */
    resultRelInfo = estate->es_root_result_relations;
    for (i = estate->es_num_root_result_relations; i > 0; i--)
    {
        heap_close(resultRelInfo->ri_RelationDesc, NoLock);
        resultRelInfo++;
    }

    /* 同样关闭任何触发器目标关系 */
    ExecCleanUpTriggerState(estate);

    /*
     * 关闭任何为[KEY] UPDATE/SHARE所选的关系,同样保持锁定。
     */
    foreach(l, estate->es_rowMarks)
    {
        ExecRowMark *erm = (ExecRowMark *) lfirst(l);

        if (erm->relation)
            heap_close(erm->relation, NoLock);
    }
}

ExecEndNode 函数

  ExecEndNode 函数的主要功能是递归地遍历查询计划中的每个节点,并对每个节点执行特定的结束操作。这包括释放节点相关的资源关闭打开的文件和连接,以及清理节点内部状态。这个过程对于确保在查询执行完毕后,所有的资源都得到妥善处理非常重要,以避免内存泄漏和其他潜在的问题。函数通过对不同类型的节点执行不同的结束操作(如 ExecEndResultExecEndSeqScan 等),实现了对整个查询计划的全面清理。函数源码如下所示:(路径:src\backend\executor\execProcnode.c

/* ----------------------------------------------------------------
 *      ExecEndNode
 *
 *      递归地清理以'node'为根的查询计划中的所有节点。
 *
 *      此操作完成后,查询计划将无法继续处理。这应该在查询计划
 *      完全执行完毕后才调用。
 * ----------------------------------------------------------------
 */
void
ExecEndNode(PlanState *node)
{
    /*
     * 当到达树叶节点时,无需进行任何操作。
     */
    if (node == NULL)
        return;

    /*
     * 确保有足够的栈空间可用。需要在这里检查,除了在ExecProcNode()中检查,
     * 因为不能保证所有节点都能到达ExecProcNode()。
     */
    check_stack_depth();

    if (node->chgParam != NULL)
    {
        bms_free(node->chgParam);
        node->chgParam = NULL;
    }

    switch (nodeTag(node))
    {
        /*
         * 控制节点
         */
        case T_ResultState:
            ExecEndResult((ResultState *) node);
            break;
        // ... 其他控制节点的处理 ...

        /*
         * 扫描节点
         */
        case T_SeqScanState:
            ExecEndSeqScan((SeqScanState *) node);
            break;
        // ... 其他扫描节点的处理 ...

        /*
         * 连接节点
         */
        case T_NestLoopState:
            ExecEndNestLoop((NestLoopState *) node);
            break;
        // ... 其他连接节点的处理 ...

        /*
         * 物化节点
         */
        case T_MaterialState:
            ExecEndMaterial((MaterialState *) node);
            break;
        // ... 其他物化节点的处理 ...

        default:
            elog(ERROR, "无法识别的节点类型: %d", (int) nodeTag(node));
            break;
    }
}

总结

  以上内容描述了 PostgreSQL 数据库中的 ExecEndNode 函数,这是一个用于递归清理查询计划中所有节点的重要功能。该函数在查询计划执行完毕后被调用,负责释放各个节点占用的资源关闭相关文件和连接、以及清理内部状态。它通过检查每个节点的类型,并对不同类型的节点调用相应的结束处理函数(如 ExecEndResultExecEndSeqScan 等),来确保资源得到妥善管理。这个过程对于维护数据库系统的稳定性和效率至关重要,能有效防止内存泄露和其他潜在问题。文章来源地址https://www.toymoban.com/news/detail-798832.html

到了这里,关于【PostgreSQL内核学习(二十三)—— 执行器(ExecEndPlan)】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 造个轮子-任务调度执行小框架-任务清单执行器实现

    okey,上一篇文章我们提到了,如何实现它的一个清单的一个代理。这里的话我们来捋一捋我们的这个执行流程是啥: 所以的话,我们的我们这里今天要做的是这个执行器的一个执行。当然这里的话,我们也是分两个部分,因为这个执行器的话,是分两个部分的,一个是正常的

    2024年02月13日
    浏览(36)
  • Junit执行器Runner探索之旅

    单元测试是每个程序员必备的技能,而Runner是每个单元测试类必有属性。本文通过解读Junit源码,介绍junit中每个执行器的使用方法,让读者在单元测试时,可以灵活的使用Runner执行器。 在今年的敏捷团队建设中,京东物流通过Suite执行器实现了一键自动化单元测试。Juint除了

    2024年02月08日
    浏览(28)
  • PgSQL-执行器机制-Unique算子

    PgSQL-执行器机制-Unique算子 PgSQL中输出去重的元组有多种方法,比如通过HashAgg或者GroupAgg。这里我们介绍第三种方法,通过Unique算子来完成这个功能。当然语句上可以是:select distinct(id1) from t; 执行器执行算子的函数都是ExecXXX,其中XXX代表某个算子。Unique算子的执行是由函数

    2024年02月07日
    浏览(23)
  • 机械臂速成小指南(五):末端执行器

    👨‍🏫🥰🥳需要机械臂相关资源的同学可以在评论区中留言哦🤖😽🦄 指南目录📖: 🎉🎉机械臂速成小指南(零点五):机械臂相关资源🎉🎉 机械臂速成小指南(零):指南主要内容及分析方法 机械臂速成小指南(一):机械臂发展概况 机械臂速成小指南(二):

    2024年02月03日
    浏览(29)
  • xxl-job执行器无法自动注册

    问题描述 在springboot项目里配置了xxl-job2.3.0,但是执行器无法自动注册 yaml配置如下: 执行器无法自动注册到xxl-job-admin 排查过程 经过debug发现,是spring没有加载xxlJobExecutor这个Bean debug流程(SpringApplication.run()–SpringApplication.refreshContext()–SpringApplication.refresh() --SpringApplication

    2024年02月16日
    浏览(25)
  • Camunda 7.x 系列【53】Job 执行器

    有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 2.7.9 本系列Camunda 版本 7.19.0 源码地址:https://gitee.com/pearl-organization/camunda-study-demo Job Executor 即任务执行器,是 Camunda 中的一个调度组件,负责执行异步后台作业。 Job 表示 Job Executor 执行的某一作业,例如,在定

    2024年02月09日
    浏览(28)
  • Spring Boot 中的任务执行器是什么,如何使用

    Spring Boot 是一个非常流行的 Java 开发框架,它的核心理念是通过简单的配置和约定来提高开发效率。在很多情况下,我们需要在后台执行一些任务,比如异步处理、定时任务等等。为了简化这些任务的开发和管理,Spring Boot 提供了一个任务执行器(Task Executor)。 任务执行器

    2024年02月15日
    浏览(27)
  • 【源码分析】XXL-JOB的执行器的注册流程

    目的:分析xxl-job执行器的注册过程 流程: 获取执行器中所有被注解( @xxlJjob )修饰的 handler 执行器注册过程 执行器中任务执行过程 版本: xxl-job 2.3.1 建议:下载 xxl-job 源码,按流程图 debug 调试, 看堆栈信息并按文章内容理解执行流程 。 完整流程图: 部分流程图: 首先启

    2023年04月22日
    浏览(31)
  • xxl-job中在分片的时候项目模块如何开启多个执行器?

    在xxl-job中,要在分片时开启多个执行器,您需要按照以下步骤进行操作: 1.在xxl-job的项目中,找到对应的模块(即需要开启多个执行器的模块)。 2.在模块的配置文件(通常是application.properties或application.yml)中,找到以下属性: properties xxl.job.executor.appname=   xxl.job.executor

    2024年02月09日
    浏览(31)
  • MYSQL04高级_逻辑架构剖析、查询缓存、解析器、优化器、执行器、存储引擎

    ①. 服务器处理客户端请求 ②. 连接层 系统(客户端)访问MySQL服务器前,做的第一件事就是建立TCP连接 经过三次握手建立连接成功后,MySQL服务器对TCP传输过来的账号密码做身份认证、权限获取 用户名或密码不对,会收到一个Access denied for user错误,客户端程序结束执行用户名密码认

    2024年02月12日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包