💻 深耕数据库内核架构设计与开发十余年,曾主导多款高性能分布式数据库内核研发,攻克高并发、低延迟等核心技术难题。现倾力打造《从零手写数据库》系列教程,首次系统性公开数据库内核源码级实现细节!
一、概述
扫描节点作为计划树的叶子节点,每个数据源表都会对应一个扫描节点。
每个简单数据源表会转换为一个扫描操作符节点,当为单个数据源表时,下层只有一个扫描操作符节点。
当有多个数据源表并列时,数据源表之间是不带条件的联接关系,将数据源转换为扫描节点的同时,需要增加上层的联接节点。
二、数据源处理接口
为了可以递归重用,这里增加了一个分发函数,可以按数据源或操作符的类型调用对应的处理函数,方便递归调用。
Node* TablePlanNode(Node *node)
{
Node *subplan = NULL;
switch (node->type)
{
case T_TableRefInfo:
subplan = ScanPlanNode((TableRefInfo*)node);
break;
case T_JoinTblInfo:
subplan = JoinPlanNode((JoinTblInfo *)node);
break;
case T_NestLoopNode:
subplan = node;
break;
default:
break;
}
return subplan;
}
本节介绍普通数据源的处理,联合数据源表下节继续介绍。
三、单个数据源表
扫描节点的生成,初始化对应的扫描数据表信息和操作符算法接口,并将该数据源表标记为已经在执行计划中。
Node* ScanPlanNode(TableRefInfo *tblRefInfoNode)
{
ScanNode *scanNode = (ScanNode*)NewNode(ScanNode);
scanNode->tblRefInfoNode = (Node*)tblRefInfoNode;
scanNode->planInfo.execInfo = &seqScanStateInfo;
tblRefInfoNode->isPlan = 1;
return (Node*)scanNode;
}
四、多个数据源表
当有多个数据源表时,前两个数据源表会增加一个表联接操作节点,扫描节点作为它的左右子节点。
第三张数据源表与联接数据源再进行嵌套联接,新增一个表联接操作节点,而扫描节点作为右子树,也就是内表,原联接操作节点作为左子树。
Node* CrossJoinPlan(Node *subplan, Node *node)
{
NestLoopNode *nlNode = NULL;
if(subplan == NULL)
{
subplan = TablePlanNode(node);
}
else
{
nlNode = NewNode(NestLoopNode);
nlNode->joinType = JOIN_CROSS;
nlNode->parserNode = NULL;
nlNode->leftplan = subplan;
nlNode->rightplan = TablePlanNode(node);
nlNode->planInfo.execInfo = &nestloopStateInfo;
nlNode->lresult = NULL;
nlNode->rresult = NULL;
subplan = (Node*)nlNode;
}
return subplan;
}
当from子句中有多个数据表时,它们就会构成嵌套级联的联接关系,用嵌套循环算法实现时,就会有多层循环。
五、总结
本节新增内容在exam_47目录下,在执行计划模块plan的plan.c中定义。
🌟 点赞收藏,分享给身边的技术伙伴,关注我们,持续获取数据库内核开发的硬核干货!一起从源码级实现到分布式架构,解锁数据库技术的每一个核心细节!🚀文章转载自开源无限,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




