查询优化-提升子查询-UNION类型

news/2024/4/29 3:26:41/文章来源:https://blog.csdn.net/pg_hgdb/article/details/137040938

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

文档用途

剖析UNION类型子查询提升的条件和过程

详细信息

注:图片较大,可在浏览器新标签页打开。

SQL:

SELECT * FROM score sc, LATERAL(SELECT * FROM student WHERE sno = 1 UNION ALL SELECT * FROM student WHERE sno = sc .sno) st WHERE st.sno > 0;

查询树结构:

分析该查询树,主查询包含2个RangeTblEntry:sc和st;其中st这个表的类型是子查询,包含2个RangeTblEntry,从SQL也可以看出这2个RangeTblEntry对应两个select查询,按照Query结构去分层该查询树为3层。

稍微简化一下,结构如下图所示:

在这里插入图片描述

打印该SQL的执行计划:

image.png

根据执行计划和查询树优化前后对比,对于UNION类型的子查询提升主要是将UNION两侧子查询提升,反映在查询树中即是这2个子查询类型的RangeTblEntry添加到主查询对应的rtable队列中,3层查询优化为2层查询结构。

提升流程:查找范围表中可以提升到父查询中的子查询。如果子查询没有特殊的特性,比如分组/聚合,那么我们可以将其合并到父查询的联接树中。此外,简单的 UNION ALL 结构的子查询可以转换为“追加关系”。

void pull_up_subqueries(PlannerInfo *root){Assert(IsA(root->parse->jointree, FromExpr));root->parse->jointree = (FromExpr *)pull_up_subqueries_recurse(root, (Node *) root->parse->jointree,NULL, NULL);Assert(IsA(root->parse->jointree, FromExpr));}

jointree中包含了FROM…WHERE…所引用的表,该递归结构通过pull_up_subqueries_recurse对其进行递归处理,所以优化执行时先去深度遍历FromExpr中的列表中的每一项成员:

if (IsA(jtnode, FromExpr)){FromExpr   *f = (FromExpr *) jtnode;ListCell   *l;Assert(containing_appendrel == NULL);foreach(l, f->fromlist){lfirst(l) = pull_up_subqueries_recurse(root, lfirst(l),lowest_outer_join,NULL);}}

如果RangeTblEntry是subquery类型并且满足简单子查询条件,使用pull_up_simple_union_all处理,该函数接受3个参数,分别是:查询树上下文, RangeTblRef, RangeTblEntry。

int varno = ((RangeTblRef *) jtnode)->rtindex;RangeTblEntry *rte = rt_fetch(varno, root->parse->rtable);if (rte->rtekind == RTE_SUBQUERY &&is_simple_union_all(rte->subquery))return pull_up_simple_union_all(root, jtnode, rte);

pull_up_simple_union_all:

根据优化后的查询树结构,提升的主要目的是把三个层次变成两个层次,那么如果“子子查询”中引用了顶层的列属性,那么这些变量应该提升一个层次,也就是调用incrementVarSublevelsUp_ rtable(rtable, -1 , 1 )。比如本例SQL:SELECT * FROM student WHERE sno = sc .sno , sc.sno 就引用了第一个层次中的列表量,它的 Var >varlevlesup 的原值是 2(相对值),子查询提升之后应该变成1。

image.png                                   image.png

在这里插入图片描述

2.下发LATERAL,本例中是(SELECT * FROM student WHERE sno = 1)和 ( SELECT * FROM student WERE sno = sc.sno )这两个子查询都变成 LATERAL,而不是只是针对引用父查询属性子查询才会拥有LATERAL语义。

image.png image.png         image.png

在这里插入图片描述
在这里插入图片描述

if (rte->lateral){ListCell   *rt;foreach(rt, rtable){RangeTblEntry *child_rte = (RangeTblEntry *) lfirst(rt);Assert(child_rte->rtekind == RTE_SUBQUERY);child_rte->lateral = true;}}

3.把第三层次的两个RangeTblEntry:(SELECT * FROM student WHERE sno = 1)和(SELECT * FROM student WHERE sno = sc.sno )两个子查询附加到第一层的 Query->rtable 列表中,在这第3步过后,后续的子查询的rtindex都将加上父查询rtindex作为偏置值。

/** Append child RTEs (and their perminfos) to parent rtable.*/CombineRangeTables(&root->parse->rtable, &root->parse->rteperminfos,rtable, subquery->rteperminfos);{*dst_rtable = list_concat(*dst_rtable, src_rtable);...}

4.开始对 subquery->setOperations 进行遍历 (pull_up_union_leaf_queries 函数),为其中的每个子查询生成一个AppendRelInfo 节点,在本例中为( SELECT * FROM student WHERE sno = 1〕和 (SELECT * FROM student WHERE sno = sc.sno )生成两个 AppendRelInfo 节点,这种类型的节点是记录到查询树的上下文中,在查询树中看不到。

SetOperationStmt *op = (SetOperationStmt *) setOp;/* Recurse to reach leaf queries */pull_up_union_leaf_queries(op->larg, root, parentRTindex, setOpQuery,childRToffset);pull_up_union_leaf_queries(op->rarg, root, parentRTindex, setOpQuery,childRToffset);appinfo = makeNode(AppendRelInfo);appinfo->parent_relid = parentRTindex;appinfo->child_relid = childRTindex;appinfo->parent_reltype = InvalidOid;appinfo->child_reltype = InvalidOid;make_setop_translation_list(setOpQuery, childRTindex, appinfo);appinfo->parent_reloid = InvalidOid;root->append_rel_list = lappend(root->append_rel_list, appinfo);
  1. 简单回顾这种类型子查询流程如下图:

image.png

到此为止,还有一个需要解决的问题:子查询提升将对应的RangeTblEntry添加到了父查询的rtable中,而且过程中更新了rtindex(第4步),这个新的RangeTblEntry不会在父查询的FromExpr中出现,所以构造完ApendRelInfo后,需要对子查询构造新的RangeTblRef,填充新的rtindex, 然后执行pull_up_subqueries_recurse。

rtr = makeNode(RangeTblRef);rtr->rtindex = childRTindex;(void) pull_up_subqueries_recurse(root, (Node *) rtr,NULL, appinfo);

最后就能得到优化后的查询树结构。

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

服务器基础知识(物理服务器云服务器)

今天我们来介绍一下服务器的基础知识 一、服务器硬件基础知识 组件说明中央处理器(CPU)CPU是服务器的大脑,负责执行计算任务和指令。服务器通常配备多个CPU核心,以支持并行处理和提高性能。关键的CPU性能指标包括时钟频率、核心数…

DDos系列攻击原理与防御原理

七层防御体系 静态过滤 命中黑名单 对确定是攻击的流量直接加入黑名单(源地址命中黑名单直接丢弃,缺乏机动性和扩展性) 畸形报文过滤 畸形报文攻击 TCP包含多个标记位,排列组合有规律 • 现象:TCP标记位全为1 …

快速熟悉ElasticSearch的基本概念

1.全文检索 全文检索是通过文本内容进行全面搜索的技术。通过全文检索可以快速地在大量文本数据中查找包含特定关键词或者短语的文档,并且返回相关的搜索结果。 检索和查询的区别 检索没有搜索条件边界,检索的结果取决于相关性,相关性计算…

命令模式(请求与具体实现解耦)

目录 前言 UML plantuml 类图 实战代码 模板 Command Invoker Receiver Client 前言 命令模式解耦了命令请求者(Invoker)和命令执行者(receiver),使得 Invoker 不再直接引用 receiver,而是依赖于…

leetcode 25 K 个一组反转链表

leetcode 25 K 个一组反转链表 原题链接 问题 给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。 k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保…

搜维尔科技:【应急演练】【工业仿真】救援模拟演练可视化仿真项目实施

安全救援综合演练系统是一套面向公共安全事故、预案管理、应急救援模拟演练的虚拟仿真解决方案,它为警察、消防以及专门的应急救援保障部门提供一个综合的应急救援培训和仿真演练平台。平台主要通过设计不同的事故模型和特定的灾难场景,定制不同的应急救…

Java毕业设计-基于springboot开发的游戏分享网站平台-毕业论文+答辩PPT(附源代码+演示视频)

文章目录 前言一、毕设成果演示(源代码在文末)二、毕设摘要展示1、开发说明2、需求分析3、系统功能结构 三、系统实现展示1、系统功能模块2、后台登录2.1管理员功能模块2.2用户功能模块 四、毕设内容和源代码获取总结 Java毕业设计-基于springboot开发的…

neo4j相同查询语句一次查询特慢再次查询比较快。

现象&#xff1a; neo4j相同查询语句一次查询特慢再次查询比较快。 分析&#xff1a; 查询语句 //查询同名方法match(path:Method) where id(path) in [244333030] and NOT path:Constructor//是rpc的方法match(rpc_method:Method)<-[:DECLARES]-(rpc_method_cls:Class) -…

React 应用实现监控可观测性最佳实践

前言 React 是一个用于构建用户界面的 JavaScript 框架。它采用了虚拟 DOM 和 JSX&#xff0c;提供了一种声明式的、组件化的编程模型&#xff0c;以便更高效地构建用户界面。无论是简单还是复杂的界面&#xff0c;React 都可以胜任。 YApi 是使用 React 编写的高效、易用、功…

GK7202V330国科微 GK7202RNCFV330 GOKE

GK7202V330 芯片是国科针对消费类 Camera 市场推出的支持 ISP 和 H.265 编码的新一代消费类 Camera SOC 芯 片。 该芯片集成专用的 ISP&#xff0c;拥有高效的视频编码处理性能&#xff0c;支持 H.265 编码&#xff0c;满足客户各种差异化业务需求。集 成了 RTC、POR、Audio …

【Pt】马灯贴图绘制过程 02-制作锈迹

目录 一、边缘磨损效果 二、刮痕效果 三、边缘磨损与刮痕的混合 四、锈迹效果 本篇效果&#xff1a; 一、边缘磨损效果 将智能材质“Iron Forge Old” 拖入图层 打开“Iron Forge Old” 文件夹&#xff0c;选中“Sharpen”&#xff08;锐化&#xff09;&#xff0c;增大“…

【QT入门】 QListWidget各种常见用法详解之图标模式

往期回顾 【QT入门】 Qt代码创建布局之多重布局变换与布局删除技巧-CSDN博客 【QT入门】 QTabWidget各种常见用法详解-CSDN博客 【QT入门】 QListWidget各种常见用法详解之列表模式-CSDN博客 【QT入门】 QListWidget各种常见用法详解之图标模式 QListWidget有列表和图标两种显…

Python-VBA编程500例-024(入门级)

字符串写入的行数(Line Count For String Writing)在实际应用中有着广泛的应用场景。常见的应用场景有&#xff1a; 1、文本编辑及处理&#xff1a;在编写或编辑文本文件时&#xff0c;如使用文本编辑器或文本处理器&#xff0c;经常需要处理字符串并确定其在文件中的行数。这…

如何在Win10使用IIS服务搭建WebDAV网站并实现无公网IP访问内网文件内容

文章目录 前言1. 安装IIS必要WebDav组件2. 客户端测试3. 使用cpolar内网穿透&#xff0c;将WebDav服务暴露在公网3.1 安装cpolar内网穿透3.2 配置WebDav公网访问地址 4. 映射本地盘符访问 前言 在Windows上如何搭建WebDav&#xff0c;并且结合cpolar的内网穿透工具实现在公网访…

深入MNN:开源深度学习框架的介绍、安装与编译指南

引言 在人工智能的世界里&#xff0c;深度学习框架的选择对于研究和应用的进展至关重要。MNN&#xff0c;作为一个轻量级、高效率的深度学习框架&#xff0c;近年来受到了众多开发者和研究人员的青睐。它由阿里巴巴集团开源&#xff0c;专为移动端设备设计&#xff0c;支持跨平…

keil调试仿真退出卡死现象解决办法

更新到keil5版本V5.20之后&#xff0c;目前一直到V5.29版本&#xff0c;都存在一个问题&#xff1a; 退出调试模式时&#xff0c;有可能会卡死&#xff01; 此时需要在任务管理器中结束掉进程才能强制关闭keil工程。 网上查找了很多资料&#xff0c;一种是退出仿真时不能有断…

python读取excel,转换成json格式,for国际化前端菜单

# -*- coding: utf-8 -*-import pandas as pd import json# 读取Excel文件中的数据 excel_file rD:\解析excel\中英.xlsx df pd.read_excel(excel_file)# 生成中文JSON和英文JSON cn_data {} en_data {} pu_data {} special_data_cn {} special_data_en {} special_data…

Flink系列之:Flink SQL Gateway

Flink系列之&#xff1a;Flink SQL Gateway 一、Flink SQL Gateway二、部署三、启动SQL Gateway四、运行 SQL 查询五、SQL 网关启动选项六、SQL网关配置七、支持的端点 一、Flink SQL Gateway SQL 网关是一项允许多个客户端从远程并发执行 SQL 的服务。它提供了一种简单的方法…

HarmonyOS实战开发-实现带有卡片的电影应用

介绍 本篇Codelab基于元服务卡片的能力&#xff0c;实现带有卡片的电影应用&#xff0c;介绍卡片的开发过程和生命周期实现。需要完成以下功能&#xff1a; 元服务卡片&#xff0c;用于在桌面上添加2x2或2x4规格元服务卡片。关系型数据库&#xff0c;用于创建、查询、添加、删…

目前常见的搜索引擎有哪些?

常见的搜索引擎可以分为两类&#xff1a;全网搜索类和平台内搜索。 全网搜索类是指可以在互联网范围内进行搜索的引擎&#xff0c;它们提供了广泛的搜索结果&#xff0c;包括网页、图片、视频、新闻等各种类型的内容。以下是一些常见的全网搜索引擎&#xff1a; 百度&#xff…