Postgresql源码(133)优化器动态规划生成连接路径的实例分析

  • 物理算子的生成分为两步,基表的扫描路径生成set_base_rel_pathlists;连接路径生成(make_rel_from_joinlist动态规划)。本篇简单分析实现。
  • 看过代码会发现,“基表的扫描路径生成”其实就是作为连接路径生成dp计算的第一层数据,然后逐层拼接上新的连接节点,每层选一个局部最优的 在留几个有序的,就进入到下一层计算。一般有几张表相连就会有几层计算。
  • 入口函数:make_one_rel

1 物理算子基表扫描路径生成set_base_rel_pathlists

  • set_base_rel_sizes
    • 为查询计划中每个基本关系估计大小;预估的行数、行宽;决定是否并行。
  • set_base_rel_pathlists
    • 为查询计划中每个基本关系找到所有可用的扫描路径。包括顺序扫描、索引扫描。识别出所有扫描路径将它们附加到对应基本关系的 pathlist 字段中。

生成基础关系的path:set_base_rel_pathlists,执行后生成的PATH在RelOptInfo数组中保存:

(gdb) p *root->simple_rel_array[1]->pathlist
$37 = {type = T_List, length = 2, max_length = 5, elements = 0x2a2aa40, initial_elements = 0x2a2aa40}

RelOptInfo数组和RTE数组是对应的:

(gdb) p root->simple_rte_array[1]->relid
$40 = 16471

生成结果实例

在这里插入图片描述

2 物理算子连接路径生成make_rel_from_joinlist

经过set_base_rel_pathlists生成扫描路径,每个基表的RelOptInfo都记录了若干条path,这些基表作为扫描的基础节点,再次基础上继续构造连接物理算子。

standard_join_search用动态规划方法来尝试不同的连接顺序和组合:

  • 初始化:从initial_rels提供的初始关系开始,dp的起点。
  • 逐层连接:每一层都会尝试将现有的连接关系与另一个关系结合,形成新的连接关系。
  • 搜索连接顺序:对于每一对可能的连接关系,函数会考虑所有可能的连接方法(如嵌套循环连接、散列连接等),生成一个或多个path。
  • 评估和选择:每个生成的path都会评估成本,优化器会选择成本最低的path作为该连接步骤的最佳路径。
  • 最终结果:返回将所有原始关系连接在一起的结果。
make_rel_from_joinliststandard_join_search...// levels_needed = 3 三张表root->join_rel_level = (List **) palloc0((levels_needed + 1) * sizeof(List *));
  • 这里是第一层,有三个RelOptInfo(student、course、teacher)
	root->join_rel_level[1] = initial_rels;
  • 从第2层开始处理:
	for (lev = 2; lev <= levels_needed; lev++){ListCell   *lc;
  • 搜索一个层级,拿到的所有RelOptInfo可能得组合,把可能的组合放到root->join_rel_level[lev]中。
  • join_rel_level[lev]记录的是RelOptInfo指针,每个RelOptInfo表示一个关系,一个关系可能带多个path。
		join_search_one_level(root, lev);
  • 在连接搜索的一个层级完成后,为每个连接关系生成额外的路径(如分区连接路径和聚合路径),并确定每个连接关系成本最低路径:
		foreach(lc, root->join_rel_level[lev]){rel = (RelOptInfo *) lfirst(lc);generate_partitionwise_join_paths(root, rel);if (!bms_equal(rel->relids, root->all_query_rels))generate_useful_gather_paths(root, rel, false);/* Find and save the cheapest paths for this rel */set_cheapest(rel);}}

三层路径生成实例

  • 第一层有三张基表的RelOptInfo
    • RelOptInfo
      • path : student(seq)
      • path : student(idx)
    • RelOptInfo
      • path : score(seq)
      • path : score(索引)
      • path : score(覆盖索引)
    • RelOptInfo
      • path : course(seq)
      • path : course(索引)
      • path : course(覆盖索引)
    • 虽然seq的代价最小,但第一层也保留了索引扫的path,因为本层代价最小的情况不一定是全局代价最小的情况,还需要保留一些有序的path方便后面节点使用。
  • 第二层返回了两个RelOptInfo,里面的路径都是两张表拼接的结果
    • RelOptInfo
      • path : Hash(score(seq), student(seq))
    • RelOptInfo
      • path : Hash(score(seq), course(seq)) <<<< 第三层选择
      • path : Nestloop(score(索引), Material(course(seq)))
      • path : Nestloop(score(覆盖索引), Material(course(seq)))
  • 第三层返回了一个RelOptInfo,代表最终路径
    • RelOptInfo
      • path : Hash(Hash(score(seq), student(seq)),course(seq))

在这里插入图片描述

3 实例

drop table student;
create table student(sno int primary key, sname varchar(10), ssex int);
insert into student values(1, 'stu1', 0);
insert into student values(2, 'stu2', 1);
insert into student values(3, 'stu3', 1);
insert into student values(4, 'stu4', 0);drop table course;
create table course(cno int primary key, cname varchar(10), tno int);
insert into course values(1, 'meth', 10);
insert into course values(2, 'english', 11);drop table teacher;
create table teacher(tno int primary key, tname varchar(10), tsex int);
insert into teacher values(10, 'te1', 1);
insert into teacher values(11, 'te2', 0);drop table score;
create table score (sno int, cno int, degree int);
create index idx_score_sno on score(sno);
insert into score values (1, 10, 100);
insert into score values (1, 11, 89);
insert into score values (2, 10, 99);
insert into score values (2, 11, 90);
insert into score values (3, 10, 87);
insert into score values (3, 11, 20);
insert into score values (4, 10, 60);
insert into score values (4, 11, 70);explain 
SELECT * 
FROM STUDENT 
LEFT JOIN SCORE ON STUDENT.sno = SCORE.sno
LEFT JOIN COURSE ON SCORE.cno = COURSE.cno;

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

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

相关文章

【Mac】MWeb Pro(好用的markdown编辑器) v4.5.9中文版安装教程

软件介绍 MWeb Pro for Mac是一款Mac上的Markdown编辑器软件&#xff0c;它支持实时预览&#xff0c;语法高亮&#xff0c;自动保存和备份等功能&#xff0c;并且有多种主题和样式可供选择。此外&#xff0c;MWeb还支持多种导出格式&#xff0c;包括HTML、PDF、Word、ePub等&a…

栈和队列的经典例题,LeetCode 括号匹配问题;栈实现队列;队列实现栈;队列带环问题

1.前序 又有很久没有更新文章了&#xff0c;这次带你们手撕几道基础题&#xff1b;真的就和康纳吃饭一样简单&#xff01;&#xff01;&#xff01; 如果还不会队列和栈的可以去看看之前写的博客&#xff1b; 栈的实现 队列概念以及实现 <- 快速传送 目录 1.前序 …

自定义全局变量3

变量删除 语法 unset var_name演示 自定义常量 介绍 就是变量设置值以后不可以修改的变量叫常量, 也叫只读变量 语法 readonly var_name演示 自定义全局变量 父子Shell环境介绍 例如: 有2个Shell脚本文件 A.sh 和 B.sh 如果 在A.sh脚本文件中执行了B.sh脚本文件, 那么A.…

【Web】CISCN 2024初赛 题解(全)

目录 Simple_php easycms easycms_revenge ezjava mossfern sanic Simple_php 用php -r进行php代码执行 因为ban了引号&#xff0c;考虑hex2bin&#xff0c;将数字转为字符串 php -r eval(hex2bin(16进制)); 注意下面这段报错&#xff0c;因为加不了引号&#xff0c;开…

链表-设计LRU缓存结构

题目描述&#xff1a; 代码实现&#xff1a;这里记录了根据LRU算法原理最直接理解的代码实现。 import java.util.*;//存储输入内容&#xff0c;记录访问权值 class CounterInfo {int key;int value;int times;//代表key对应的权值&#xff0c;值越小优先级越高public Counter…

【第2章】SpringBoot配置文件

文章目录 前言一、编写配置信息1. properties2. yml 二、获取配置信息1.直接获取2.配置类形式 总结 前言 SpringBoot工程创建后&#xff0c;会为我们提供一个默认的配置文件(application.properties)&#xff0c;配置文件主要用于那些可能发生变化且经常改变的属性值。 一、编…

Autodesk 3DS Max v2025 解锁版安装教程 (3D 建模软件)

前言 Autodesk 3ds Max 是一款功能强大的 3D 建模和动画解决方案&#xff0c;游戏开发人员、视觉效果艺术家和平面设计师使用它来创建庞大的世界、令人惊叹的场景和引人入胜的虚拟现实 (VR) 体验。 Autodesk 3DS MAX是业界使用最广泛的3D建模和动画软件程序之一&#xff0c;它…

盲盒小程序开发,数字化发展下的优势

近年来&#xff0c;盲盒经济得到了快速发展&#xff0c;不少人开始加入到盲盒大军中&#xff0c;盲盒市场规模不断扩大。 盲盒最大的特点就是能够给消费者带来拆盒的刺激性和惊喜感。盲盒商品大多是动漫手办、周边等&#xff0c;具有较大的收藏价值&#xff0c;因此深深吸引着…

OpenAI模型GPT-4o、GPT-4、Gemini 1.5性能比较

大家好&#xff0c;OpenAI最新推出的GPT-4o&#xff0c;标志着人工智能语言模型和交互方式迈入了新纪元。最引人注目的是&#xff0c;GPT-4o支持实时互动和流畅的对话切换&#xff0c;让交流更加自然。 本文将对比分析GPT-4o、GPT 4以及谷歌的Gemini和Unicorn模型&#xff0c;…

JVM-调优之-如何使用arthas-观察jvm-cpu-内存-垃圾回收等信息

前言&#xff1a; 可以简单代替把dump文件下载下来后用visualvm分析了&#xff1b;跟visualvm类似的&#xff1b; docker中如何安装arthas看这个&#xff1a;docker中怎么使用arthas_arthas 集成到容器镜像-CSDN博客 curl -O https://arthas.aliyun.com/arthas-boot.jar wget …

软考之零碎片段记录(三十一)+复习巩固(错题整理,知识点总结,易错题)

1. 奇偶校验 只能检测一位数的错误。但无法纠正错误。若有奇数个数据位出错&#xff0c;可检测。有局限性。 2. 深度与广度优先遍历 参考题【【数据结构自用】1.图深度优先遍历2.找有向图中的强连通分量数目3.给出图的任意两个拓扑序列】https://www.bilibili.com/video/BV…

在Github上寻找安装ROS软件包

1、创建一个功能包 并下载git sudo apt install git 2、找到自己想在github上要克隆的包 复制此链接 3、克隆到本地 git clone 链接 4.scripts目录用于放置脚本文件和python程序 使用脚本安装编译需要的依赖库 5、下载完成后&#xff0c;在~catkin_ws目录下运行catkin_make进…

HTTP响应的基本概念

目录 HTTP响应中的一些信息 HTTPS HTTP响应中的一些信息 状态码&#xff1a;描述了这次HTTP请求是否成功&#xff0c;以及失败的原因。 1&#xff09;200 ---OK 表示这次访问成功了。 2&#xff09;404 ---Not Found 表示客户端请求的资源在服务器这边不存在。 3&a…

SRE视角下的DevOps:构建稳定高效的软件交付流程

SRE 和 DevOps 有什么区别和联系&#xff1f;本文对此进行了解读&#xff0c;并着重从 SRE 实践出发阐述了 DevOps 的建设思路。 SRE 就是在用软件工程的思维和方法论完成以前由系统管理员团队手动完成的工作。SRE 的职责是运维一个服务&#xff0c;该服务由一些相关的系统组件…

【深度学习】yolov8 seg实例分割训练,交通灯

文章目录 一、类别定义二、标注后再清洗数据三、训练yolov8 seg四、部署五、代码资料 一、类别定义 类别0&#xff1a; 类别1&#xff1a; 类别2&#xff1a; 类别3&#xff1a; 类别4&#xff1a; 类别5&#xff1a; 类别6&#xff1a; 类别7&#xff1a; 二、标注后再清洗…

同名在线查询系统微信小程序源码下载支持多种流量主,附带系统教程

同名在线查询系统微信小程序源码下载支持多种流量主这是一款支持查询同名的一款微信小程序 该款小程序支持多种查询模式 重名查询&#xff0c;热度查询&#xff0c;概率香查询 源码免费下载地址抄笔记(chaobiji.cn)

Keras深度学习框架第二十讲:使用KerasCV中的Stable Diffusion进行高性能图像生成

1、绪论 1.1 概念 为便于后文讨论&#xff0c;首先进行相关概念的陈述。 Stable Diffusion&#xff1a;Stable Diffusion 是一个在图像生成领域广泛使用的技术&#xff0c;尤其是用于文本到图像的转换。它基于扩散模型&#xff08;Diffusion Models&#xff09;&#xff0c;这…

Aiseesoft iPhone Unlocker for Mac激活版:一键解锁工具

在数字时代&#xff0c;手机解锁问题时常困扰着我们。Aiseesoft iPhone Unlocker for Mac作为一款专为Mac用户打造的解锁工具&#xff0c;以其简洁易用的界面和强大的功能&#xff0c;成为了解决iPhone解锁问题的最佳选择。 Aiseesoft iPhone Unlocker for Mac激活版下载 Aisee…

redisson 使用fastJson2序列化

前因&#xff1a;一个项目&#xff1a;有人用redisTemplete存数据&#xff08;使用了fastjson2&#xff09;&#xff0c;使用redisson取的时候就会报错。要让redisTemplete与redisson序列化一致 一、自定义序列化器 import com.alibaba.fastjson2.JSON; import com.alibaba.fa…