查询优化-ANY类型子连接提升

news2024/11/29 16:32:18

瀚高数据库
目录
文档用途
详细信息

文档用途
已知查询树基本结构的基础上,在一定条件下对SQL中的子连接提升,

详细信息
子连接提升流程
SQL:

SELECT sname FROM student WHERE sno > ANY (SELECT sno FROM score);

图1.1是该SQL对应的查询树:

image.png

优化后为:

image.png

图1.2是优化后的查询树结构,对应的SQL如下:

SELECT sname FROM STUDENT SEMI JOIN (SELECT sno FROM SCORE) ANY subquery WHERE STUDENT. sno > ANY subquery.sno;

根据SQL和查询树前后对比发现:子查询提升涉及到的对查询树的改写主要包括:

1.RangeTblEntry多出一项用来描述提升后的子查询

2.主查询中的JoinTree也进行改写,新的JoinExpr来描述半连接。

下边给出提升过程对查询树重写的具体过程。

首先明确提升子连接的函数调用关系:

image.png

分析pull_up_sublinks_jointree_recurse函数:

对出现在jointree的三种节点类型分别处理,这是一个递归的过程。

第一种FromExpr:遍历fromlist列表,保存引用的表和遍历的节点,保存表为以后判断使用:因为子连接能提升的必要条件之一是TestExpr中必须包含父查询的列属性(要不然不构成连接关系)并且TestExpr中出现的表应该是上层查询中表的子集。

/* First, recurse to process children and collect their relids */



foreach(l, f->fromlist)

{

Node    *newchild;

Relids childrelids;

newchild = pull_up_sublinks_jointree_recurse(root,

lfirst(l),

&childrelids);

newfromlist = lappend(newfromlist, newchild);

frelids = bms_join(frelids, childrelids);

}

第二种:RangeTblRef,这种节点不会再有下层节点,作为递归出口,所以只需要记录表达式中变量引用的表

int varno = ((RangeTblRef *) jtnode)->rtindex;
*relids = bms_make_singleton(varno);

第三种:JoinExpr:表示显示的连接关系,比如某些情况下连接3个表,那么JoinExpr的下的左孩子或者右孩子仍然是JoinExpr,这种仍然需要递归处理。

j->larg = pull_up_sublinks_jointree_recurse(root, j->larg,

				&leftrelids);

j->rarg = pull_up_sublinks_jointree_recurse(root, j->rarg,

				&rightrelids);

针对本例,接下来要构造一个新的FromExpr来描述优化后SQL中的…FROM … WHERE 结构,这部分由

pull_up_sublinks_qual_recurse完成,最终的JoinTree将是这个新的FromExpr。

 

/* Build the replacement FromExpr; no quals yet */

newf = makeFromExpr(newfromlist, NULL);

/* Set up a link representing the rebuilt jointree */

jtlink = (Node *) newf;

/* Now process qual --- all children are available for use */

newf->quals = pull_up_sublinks_qual_recurse(root, f->quals,

						&jtlink, frelids,

							NULL, NULL);

分析pull_up_sublinks_qual_recurse():

整体上看这部分对应于优化后的查询树的JoinExpr节点的建立,包括JoinExpr结构体中的左操作数、右操作数、连接关系描述。

if ((j = convert_ANY_sublink_to_join(root, sublink,available_rels1)) != NULL)

{



j->larg = *jtlink1;

*jtlink1 = (Node *) j;





j->rarg = pull_up_sublinks_jointree_recurse(root,

j->rarg,

&child_rels);





j->quals = pull_up_sublinks_qual_recurse(root,

j->quals,

&j->larg,

available_rels1,

&j->rarg,

child_rels);



/* Return NULL representing constant TRUE */

return NULL;

			}

分析convert_ANY_sublink_to_join(),生成新的RangeTblEntry,添加到原查询树的rtable,计算rtindex

nsitem = addRangeTableEntryForSubquery(pstate,subselect,makeAlias("ANY_subquery", NIL),false,false);

rte = nsitem->p_rte;

parse->rtable = lappend(parse->rtable, rte);

rtindex = list_length(parse->rtable);

生成新的RangeTblRef

rtr = makeNode(RangeTblRef);

rtr->rtindex = rtindex;

对于新的JoinExpr需要生成新的quals,在这里要对testexpr进行替换,把Param替换成Var

quals = convert_testexpr(root, sublink->testexpr, subquery_vars);

替换规则:Param必然是子查询TargetList中的某一项,根据Param中的paramid获得该属性的列表下标:

if (param->paramkind == PARAM_SUBLINK)

{

if (param->paramid <= 0 ||

param->paramid > list_length(context->subst_nodes))

elog(ERROR, "unexpected PARAM_SUBLINK ID: %d", param->paramid);





return (Node *) copyObject(list_nth(context->subst_nodes,

param->paramid - 1));

}

最后填充:

/*

* And finally, build the JoinExpr node.

*/

result = makeNode(JoinExpr);

result->jointype = JOIN_SEMI;

result->isNatural = false;

result->larg = NULL; /* caller must fill this in */

result->rarg = (Node *) rtr;

result->usingClause = NIL;

result->join_using_alias = NULL;

result->quals = quals;

result->alias = NULL;

result->rtindex = 0;		/* we don't need an RTE for it */

经过上面步骤,最终生成了图1.2所示的结构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1586574.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录算法训练营第三十一天| 455.分发饼干、376.摆动序列、53.最大子序和

系列文章目录 目录 系列文章目录455.分发饼干贪心算法大饼干喂胃口大的&#xff08;先遍历胃口&#xff09;胃口大的先吃大饼干(先遍历饼干&#xff09;小饼干先喂胃口小的&#xff08;先遍历胃口&#xff09;胃口小的先吃小饼干&#xff08;先遍历饼干&#xff09; 376. 摆动序…

为什么在学校很难真正学好嵌入式?

10几年前,我是读电气工程专业,学了很多东西,结构,电机、绘图,plc等等.. 其实,都没什么鸟用,出来还是像个废物。 后面我自学转了单片机开发,说句难听点,自己买个开发板都比在学校学得深。 可能是这个专业的问题,主攻不是嵌入式方向,老师用汇编点个流水灯,这门课就…

第四百五十三回

文章目录 1. 问题描述2. 优化方法2.1 缩小范围2.2 替代方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何获取AppBar的高度"相关的内容&#xff0c;本章回中将介绍关于MediaQuery的优化.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 问题描述 我们在…

编程新手必看,python中条件控制语句学习(13)

介绍&#xff1a; Python3中的条件控制主要通过if、elif和else关键字来实现&#xff0c;它们用于根据条件执行特定的代码块。 if语句&#xff1a;这是最基本的条件控制结构。如果满足某个条件&#xff08;条件为True&#xff09;&#xff0c;则执行相应的代码块。在Python中&am…

Java学习42-Java 流(Stream)、文件(File)和IO - FileReader\FileWriter的使用

IO流 IO流的概述&#xff0c;分类等 Java程序中&#xff0c;对于数据的输入输出以stream方式进行&#xff0c;可以看作是一种数据的流动。 IO流中的IO是Input和Output的缩写&#xff0c;是非常实用的技术&#xff0c;用于处理设备之间的数据传输。读写文件&#xff0c;网络通…

Linux下批量的批量操作

批量删除docker 镜像 docker images | grep ent-form-web |awk ‘{print $3}’ | xargs docker rmi docker images: 列出所有的docker 镜像 docker images | grep ent-form-web : 选取出结果带 ent-form-web的信息 docker images | grep ent-form-web |awk ‘{print $3}’ 选取…

黑白图像彩色化

黑白图像彩色化 黑白图像彩色化&#xff0c;调用训练好的模型&#xff0c;将图片加上彩色&#xff0c;只需要OPENCV&#xff0c;支持C/PYTHON

【Python函数和类3/6】函数的返回值

目录 知识回顾 目标 函数的返回值 Tips 练习 ​编辑return的其它特性 任意类型的返回值 返回多个值 return的位置 小结 局部变量 局部变量的作用域 全局变量 全局变量的作用域 同名变量 pi的作用域 总结 知识回顾 在上篇博客中&#xff0c;我们学习给函数设置参…

基于 S2-LP 实现 802.15.4g 帧格式的数据透传

1. 引言 S2-LP 硬件上支持 802.15.4g 的帧格式&#xff0c;但是现有的 SDK 包并没有基于该帧格式的示例工程&#xff0c;因此本篇文章将介绍如何实现基于 802.15.4g 帧格式的数据透传。 2. 802.15.4g 帧格式 在开始之前&#xff0c;需要对 802.15.4g 帧格式有一个初步的了解…

VS中使用QT的UI提升类时,找不到头文件的情况

1、情况简述 在使用VS时&#xff0c;会发现与QCreator存在一些差异。最主要的就是要设置很多东西&#xff0c;如果不配置的话&#xff0c;就会遇到一些问题。下面我分享下我调试过程中遇到的一个问题。使用Qdesigner的UI提升类时&#xff0c;找不到头文件的情况&#xff1a; …

Flutter - 环境配置提示 cmdline-tools component is missing

问题&#xff1a; flutter doctor运行命令 flutter doctor 报错&#xff1a; Android toolchain - develop for Android devices (Android SDK version 30.0.2) ✗ cmdline-tools component is missing Run path/to/sdkmanager --install "cmdline-tools;lates…

ChatGPT国内镜像站大全(全都是能白嫖的)

今天在知乎看到一个问题&#xff1a;“平民不参与内测的话没有账号还有机会使用ChatGPT吗&#xff1f;” 从去年GPT大火到现在&#xff0c;关于GPT的消息铺天盖地&#xff0c;真要有心想要去用&#xff0c;途径很多&#xff0c;别的不说&#xff0c;国内GPT的镜像站到处都是&a…

OpenHarmony4.0分布式任务调度浅析

1 概述 OpenHarmony 分布式任务调度是一种基于分布式软总线、分布式数据管理、分布式 Profile 等技术特性的任务调度方式。它通过构建一种统一的分布式服务管理机制&#xff0c;包括服务发现、同步、注册和调用等环节&#xff0c;实现了对跨设备的应用进行远程启动、远程调用、…

ES13:类的新增特性、最外层的await、at...

1-类的新增特性 类私有属性和方法&#xff1a;# class Person{// 不需要传参、一开始就需要初始化的&#xff0c;就可以在类的最外面直接声明这个成员state{a:1,b:2}constructor(name,age){this.namename;this.ageage;}}在属性和方法前加#表示私有 #obj{} #prest(){}静态成员…

DP例题详解(二)最短编辑距离和编辑距离

902. 最短编辑距离 - AcWing题库 #include<bits/stdc.h>using namespace std;const int N1010;int n,m; char a[N],b[N]; int f[N][N];int main() {cin>>n>>a1;cin>>m>>b1;for(int i0;i<m;i)f[0][i]i;for(int i0;i<n;i)f[i][0]i;//先初始化…

Leetcode算法训练日记 | day20

一、合并二叉树 1.题目 Leetcode&#xff1a;第 617 题 给你两棵二叉树&#xff1a; root1 和 root2 。 想象一下&#xff0c;当你将其中一棵覆盖到另一棵之上时&#xff0c;两棵树上的一些节点将会重叠&#xff08;而另一些不会&#xff09;。你需要将这两棵树合并成一棵新…

linux中rpm包与deb包的区别及使用

文章目录 1. rpm与deb的区别2. deb软件包的格式和使用2.1 deb软件包命令遵行如下约定2.2 dpkg命令2.3 apt-命令 3. Unix和Linux的区别Reference 1. rpm与deb的区别 有的系统只支持使用rpm包安装&#xff0c;有的只支持deb包安装&#xff0c;混乱安装会导致系统问题。 关于rpm和…

绿联 安装火狐浏览器(Firefox),支持访问路由器

绿联 安装火狐浏览器&#xff08;Firefox&#xff09;&#xff0c;支持访问路由器 1、镜像 linuxserver/firefox:latest 前置条件&#xff1a;动态公网IP。 已知问题&#xff1a; 直接输入中文时&#xff0c;不能完整输入&#xff0c;也可能输入法无法切换到中文&#xff0c;可…

【LeetCode刷题笔记】LeetCode 1365.有多少小于当前数字的数字

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 更多算法知识专栏&#xff1a;算法分析&#x1f525; 给大家跳段街舞感谢…

【STM32G431RBTx】备战蓝桥杯嵌入式→省赛试题→第十四届

文章目录 前言一、题目二、模块初始化三、代码实现interrupt.h:interrupt.c:main.h:main.c: 四、完成效果五、总结 前言 无 一、题目 二、模块初始化 1.LCD这里不用配置&#xff0c;直接使用提供的资源包就行 2.KEY, 四个按键IO口都要配置&#xff0c;分别是PB0, PB1,PB2,PA…