暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【手写数据库核心揭秘系列】第95讲 联合查询,联接表达式的执行计划生成

开源无限 2025-05-29
46


💻 深耕数据库内核架构设计与开发十余年,曾主导多款高性能分布式数据库内核研发,攻克高并发、低延迟等核心技术难题。现倾力打造《从零手写数据库》系列教程,首次系统性公开数据库内核源码级实现细节!
🚀 从存储引擎、查询优化到分布式事务,手把手拆解核心模块;从语法解析树构建到执行计划生成,逐行代码还原设计精髓
🌟 无论你是数据库开发者、系统架构师,还是对底层技术充满好奇的极客,这里都有你想要的“硬核干货”!点击关注,与行业老兵共同探索数据库技术的星辰大海!

一、概述 


多表的关联查询是数据库的一个重要的数据处理能力,体现关系代数中多个集合之间的交运算,并运算,积运算。

在前一阶段的基础上支持联合查询,需要继续做如下内容:

  1. 联接子句的处理;
  2. 实现不同联接类型的执行算子。

二、联接表达式 


在多表联接操作中,会将联接操作解析为联接子句,它由三部分组成:数据表名称、联类型和联接条件,

关联数据表大于两个时,联接子句由嵌套形式组成。联接子句中数据表的处理同from子句中一样,

对于联接类型和联接条件需要额外处理,涉及到逻辑执行计划阶段和物理执行计划阶段。


联接表达式转换

在逻辑执行计划阶段,对于联接条件表达式进行处理,并且将生成的联接子句结构添加到JoinList当中,

在进行物理计划生成时,会优先处理联接子句,再处理其它数据表。当联接子句为嵌套形式时,递归处理它的左右子节点,直到叶子节点为常量或属性列为止。

    ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
    int JoinTblInfoNodeProcess(QueryStmt *queryStmt, JoinTblInfo *joinTblInfo)
    {
        int ret = -1;
        Node *tmp = NULL;


        if (joinTblInfo->leftTblInfo != NULL)
        {
            ret = TableNodeProcess(queryStmt, joinTblInfo->leftTblInfo);
            if(ret < 0)
                return ret;
        }


        if(joinTblInfo->rightTblInfo != NULL)
        {
           ret = TableNodeProcess(queryStmt, joinTblInfo->rightTblInfo);
           if(ret < 0)
                return ret;
        }


        joinTblInfo->isPlan = 0;
        queryStmt->joinList = AppendList(queryStmt->joinList, (Node*)joinTblInfo);


        if(joinTblInfo->joinExpr != NULL)
        {
            ret = JoinConditionProcess(queryStmt, joinTblInfo->joinExpr);
        }


        return ret;
    }


    联接条件优化

    在对联接子句处理的最后,做了一个小的优化,当联接类型为包含右联接时,包括右外联接和右自然联接,

    将该联接转换为左联接,这样就可以使用嵌套循环算法来实现。具体的做法就是将它的左右子树交换,并将联接类型从右联接改为左联接。

      ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
          * right join -> left join ,after base table */
          if(joinTblInfo->joinType & JOIN_RIGHT)
          {
              joinTblInfo->joinType &= ~JOIN_RIGHT;
              joinTblInfo->joinType |= JOIN_LEFT;


              tmp = joinTblInfo->leftTblInfo;
              joinTblInfo->leftTblInfo = joinTblInfo->rightTblInfo;
              joinTblInfo->rightTblInfo = tmp;
          }


      联接条件处理

      联接条件表达式的处理,对其中的属性列转换为目标列结构,检查属性列的合法性,查找对应的属性元数据,这与where子句中的表达式处理类似,调用相同接口进行处理。

        ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line
        int JoinConditionProcess(QueryStmt *queryStmt, Node *condition)
        {
            int ret = -1;


            ret = ExprTargetProcess((Expr*)condition, queryStmt);


            return ret;
        }

        三、总结 


        本节内容实现位于exam_52目录下的plan.c文件中。


        🌟 点赞收藏,分享给身边的技术伙伴,关注我们,持续获取数据库内核开发的硬核干货!一起从源码级实现到分布式架构,解锁数据库技术的每一个核心细节!🚀

        【往期精彩推荐】

        【手写数据库核心揭秘系列】第94讲 带过滤条件的查询演示,仓储信息的清晰可见

        【手写数据库核心揭秘系列】第93讲 选择过滤执行算子

        【手写数据库核心揭秘系列】第92讲 where选择过滤的逻辑与物理执行计划生成


        文章转载自开源无限,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

        评论