Postgresql源码(135)生成执行计划——Var的调整set_plan_references

news2024/11/8 15:35:32

1 总结

  • set_plan_references主要有两个功能:
    • 拉平:生成拉平后的RTE列表(add_rtes_to_flat_rtable)。
    • 调整:调整前每一层计划中varno的引用都是相对于本层RTE的偏移量。放在一个整体计划后,需要指向一个统一的RTE列表,所以需要把varno调整下指向拉平后的RTE表。
    • 例如下面计划中,RTE记录了6张表:
      • 1 → `{rtekind = RTE_RELATION, relid = 16656, inh = false, relkind = 114 ‘r’} -> student
      • 2 → `{rtekind = RTE_RELATION, relid = 16671, inh = false, relkind = 114 ‘r’} -> score
      • 3 → `{rtekind = RTE_JOIN, relid = 0, inh = false, relkind = 0 } -> {score join student}
      • 4 → `{rtekind = RTE_RELATION, relid = 16661, inh = false, relkind = 114 ‘r’} -> course
      • 5 → `{rtekind = RTE_JOIN, relid = 0, inh = false, relkind = 0 } -> {被优化掉的join course}
    • Result节点的第一列是STUDENT.sname,他的varno一开始是1,varattno是2,显然他不应该直接引用RTE中的某一张表,因为Result节点的数据应该使用下面SORT节点中取出来的,所以:
      • varno被调整为-2(表示引用OUTTER节点也就是LEFT树返回的结果)
      • varattno被调整1,表示从结果中拿第一列。
explain
SELECT STUDENT.sname, random(), SCORE.degree
FROM STUDENT
LEFT JOIN SCORE ON STUDENT.sno = SCORE.sno
LEFT JOIN COURSE ON SCORE.cno = COURSE.cno
ORDER BY STUDENT.sno;
                                     QUERY PLAN
------------------------------------------------------------------------------------
 Result  (cost=182.67..213.27 rows=2040 width=54)
   ->  Sort  (cost=182.67..187.77 rows=2040 width=46)
         Sort Key: student.sno
         ->  Hash Right Join  (cost=34.75..70.53 rows=2040 width=46)
               Hash Cond: (score.sno = student.sno)
               ->  Seq Scan on score  (cost=0.00..30.40 rows=2040 width=12)
               ->  Hash  (cost=21.00..21.00 rows=1100 width=42)
                     ->  Seq Scan on student  (cost=0.00..21.00 rows=1100 width=42)

上面用例经过set_plan_references调整前后的完整例子:
在这里插入图片描述

2 数据结构

PlannerInfo

当前查询优化的状态,包含了当前查询的所有信息:

  • 当前查询的目标列表(target list)
  • 子句(例如,WHERE、GROUP BY、ORDER BY 等)
  • 范围表(range table)
  • 可用的索引信息
  • 统计信息
  • 子查询和参数信息
  • 优化器的各种临时数据和结果

PlannerGlobal

全局结构,包含了跨多个查询级别的信息。例如一个包含子查询或CTE的查询中,每个子查询都会有自己的 PlannerInfo结构,会共享同一个PlannerGlobal。包含了:

  • 全局范围表(finalrtable)
  • 全局子计划列表
  • 全局初始化计划列表
  • 全局参数表达式列表
  • 重写规则和其他全局状态信息

varno宏

#define    INNER_VAR		(-1)	/* reference to inner subplan */
#define    OUTER_VAR		(-2)	/* reference to outer subplan */
#define    INDEX_VAR		(-3)	/* reference to index column */
#define    ROWID_VAR		(-4)	/* row identity column during planning */

3 set_plan_references

1 计算全局flat_rtable

set_plan_references → add_rtes_to_flat_rtable

首先把引用的rtable全部拉平到一个级别,重新排列RTE。

具体在PlannerGlobal中构造全局范围表finalrtable,所有子PlannerInfo共享的一套RTE。

	p *root->glob->finalrtable
$7 = {type = T_List, length = 5, max_length = 5, elements = 0x3085520, initial_elements = 0x3085520}

add_rtes_to_flat_rtable后生成五个RTE:

  • RangeTblEntry {rtekind = RTE_RELATION, relid = 16656, inh = false, relkind = 114 'r'}
  • RangeTblEntry {rtekind = RTE_RELATION, relid = 16671, inh = false, relkind = 114 'r'}
  • RangeTblEntry {rtekind = RTE_JOIN, relid = 0, inh = false, relkind = 0}
  • RangeTblEntry {rtekind = RTE_RELATION, relid = 16661, inh = false, relkind = 114 'r'}
  • RangeTblEntry {rtekind = RTE_JOIN, relid = 0, inh = false, relkind = 0}

PlannerInfo→PlannerGlobal:

2 开始修正RTE的引用

set_plan_references → set_plan_refs

2.1 处理Result

  • set_plan_refs

    • case T_Result: 处理result子树
    • plan->lefttree = set_plan_refs(root, plan->lefttree, rtoffset); 递归处理左树
    • plan->righttree = set_plan_refs(root, plan->righttree, rtoffset); 递归处理右树
  • 根据内层的sort节点,重新排列result节点的三个var的varno和varattno,result已经是最外层节点了,当前使用到的var还是从sort节点继承的,需要修复下。

处理前 vs 处理后
在这里插入图片描述

set_plan_refs处理T_Result节点:

set_plan_refs
	...
	...
	case T_Result:
		Result     *splan = (Result *) plan;
		if (splan->plan.lefttree != NULL)
			set_upper_references(root, plan, rtoffset);
				...
				...
				// subplan 是 SORT节点
				// subplan->targetlist 中返回三列:STUDENT.sname, SCORE.degree,  STUDENT.sno
				// 注意缺了一列random函数
				subplan_itlist = build_tlist_index(subplan->targetlist);	
  • subplan->targetlist
    • varno = 1, varattno = 2, vartype = 1043
    • varno = 2, varattno = 3, vartype = 23
    • varno = 1, varattno = 1, vartype = 23
  • subplan_itlist
    • subplan_itlist->tlist = subplan->targetlist
    • subplan_itlist->vars[0] = {varno = 1, varattno = 2, resno = 1, varnullingrels = 0x0}
    • subplan_itlist->vars[1] = {varno = 2, varattno = 3, resno = 2, varnullingrels = ...}
    • subplan_itlist->vars[2] = {varno = 1, varattno = 1, resno = 3, varnullingrels = 0x0}
				foreach(l, plan->targetlist)
					...
					newexpr = fix_upper_expr(...)
					...
				// 计算完成
				plan->targetlist = output_targetlist;
  • output_targetlist
    • expr = 0x308f0c8, resno = 1, resname = 0x2f4d670 "sname"
      • varno = OUTER_VAR = -2, varattno = 1, vartype = 1043
    • expr = 0x308f1b8, resno = 2, resname = 0x2f4d7e8 "random"
      • funcid = 1598, funcresulttype = 701, funcretset = false
    • expr = 0x308f258, resno = 3, resname = 0x2f4d928 "degree"
      • varno = OUTER_VAR = -2, varattno = 2, vartype = 23
    • expr = 0x308f2f8, resno = 4, resname = 0x0, ressortgroupref = 1
      • varno = OUTER_VAR = -2, varattno = 3, vartype = 23

2.2 处理SORT

  • set_plan_refs
    • case T_Sort: 处理sort子树set_dummy_tlist_references
    • plan->lefttree = set_plan_refs(root, plan->lefttree, rtoffset); 递归处理左树
    • plan->righttree = set_plan_refs(root, plan->righttree, rtoffset); 递归处理右树

排序只需要引用下面一层的结果即可。

// These plan types don't actually bother to evaluate their
// targetlists, because they just return their unmodified input
// tuples.  Even though the targetlist won't be used by the
// executor, we fix it up for possible use by EXPLAIN (not to
// mention ease of debugging --- wrong varnos are very confusing).

set_dummy_tlist_references

2.3 处理Hash Right Join

  • set_plan_refs
    • case T_HashJoin: 处理join子树set_join_references
    • plan->lefttree = set_plan_refs(root, plan->lefttree, rtoffset); 递归处理左树
    • plan->righttree = set_plan_refs(root, plan->righttree, rtoffset); 递归处理右树

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

4 用例

explain
SELECT STUDENT.sname, random(), SCORE.degree
FROM STUDENT
LEFT JOIN SCORE ON STUDENT.sno = SCORE.sno
LEFT JOIN COURSE ON SCORE.cno = COURSE.cno
ORDER BY STUDENT.sno;
                                     QUERY PLAN
------------------------------------------------------------------------------------
 Result  (cost=182.67..213.27 rows=2040 width=54)
   ->  Sort  (cost=182.67..187.77 rows=2040 width=46)
         Sort Key: student.sno
         ->  Hash Right Join  (cost=34.75..70.53 rows=2040 width=46)
               Hash Cond: (score.sno = student.sno)
               ->  Seq Scan on score  (cost=0.00..30.40 rows=2040 width=12)
               ->  Hash  (cost=21.00..21.00 rows=1100 width=42)
                     ->  Seq Scan on student  (cost=0.00..21.00 rows=1100 width=42)

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

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

相关文章

Cochrane Library循证医学数据库的介绍及文献下载

今天要讲的数据库是Cochrane Library循证医学数据库,我们先来了解一下该数据库: Cochrane Library是国际Cochrane Collaboration的主要产品,由英国Wiley InterScience公司出版发行。是一个提供高质量证据的数据库,是循证医学的证…

如何把试卷上的字去掉再打印?分享三种方法

如何把试卷上的字去掉再打印?随着科技的不断发展,现代教育和学习方式也在逐渐变革。在学习过程中,我们经常需要对试卷进行整理和分析,以便更好地掌握知识点和复习。然而,传统的试卷整理方法往往效率低下且容易出错。幸…

前端实现大文件分片并行上传、断点续传、秒传(完整解析)

一、总体流程图 二、具体步骤 简单理解:前端先将文件切割多份,在进行上传,由后端进行切片合并操作。 具体逻辑: 1. 前端选中上传文件(如果是批量上传就把选中的文件存入选中文件列表数组中,后续在遍历上…

java版CRM客户关系管理系统源码:CRM客户关系管理系统的功能详解

CRM客户关系管理系统是一款功能全面的客户管理工具,旨在帮助企业和销售团队提高客户管理效率,优化销售流程。该系统包含多个模块,覆盖了从线索到回款的全流程管理,为用户提供了一个集成化的客户关系管理平台。 一、待办事项模块&a…

Python 技巧分享:NEF 文件的元数据提取

介绍 随着摄影技术的不断发展,NEF 文件作为尼康相机的 RAW 格式文件,因其包含丰富的图像数据和元数据,备受摄影爱好者和专业摄影师的青睐。提取 NEF 文件中的元数据对照片管理、分析及处理具有重要意义。本文将介绍如何使用 Python 技术&…

nltk报错Error loading stopwords: <urlopen error [Errno 11004]

最佳解决方案是手动下载并安装 nltk 数据。这里是详细步骤,确保每一步都能正确执行: 步骤 1: 手动下载 stopwords 数据集 下载 stopwords 数据集: 打开浏览器,访问以下链接下载 stopwords 数据集: stopwords.zip 解…

sap 应用日志-Application Log

文章目录 sap 应用日志-Application Log概念事务代码函数创建程序显示配置文件运行结果弹出式全屏式 程序剖析清空日志创建日志模拟数据添加日志消息显示日志BAL_DSP_LOG_DISPLAY-显示内存消息 全部程序 sap 应用日志-Application Log 概念 SAP 应用日志(Applicat…

【亚马逊云科技 CSDN 联合巨献】 「对话AI 构建者:从基础到应用的 LLM 全景培训」 限时免费!

🚀🌟【亚马逊云科技 & CSDN 联合巨献】 📚「对话AI 构建者:从基础到应用的 LLM 全景培训」🔥 限时免费! 📆 抓紧时间!6月7日前注册,原价 399,现在仅需 0…

网络编程(五)

网络编程(五) 网络服务器超时检测使用select进行超时检测套接字属性**getsockopt:获取socket软通道的某项属性值**setsockopt:设置socket软通道的某项属性值**(socket建立之后就可使用) 信号**signal():信号处理函数se…

【Python】搭配 Python 环境(超详细教程)

要想能够进行 Python 开发,就需要搭建好 Python 的环境。 需要安装的环境主要是两个部分: 运行环境:Python 开发环境:PyCharm 一、安装 Python 1、找到官方网站 Welcome to Python.org 在搜索引擎中搜索 python 关键字&…

【WP】猿人学13_入门级cookie

https://match.yuanrenxue.cn/match/13 抓包分析 抓包分析发现加密参数是cookie中有一个yuanrenxue_cookie 当cookie过期的时候&#xff0c;就会重新给match/13发包&#xff0c;这个包返回一段js代码&#xff0c;应该是生成cookie的 <script>document.cookie(y)(u)(a…

Linux环境---在线安装jdk

Linux环境—在线安装jdk 一、使用步骤 1.安装环境 JDK版本&#xff1a;1.8 1.1 建立存放软件的目录 注意&#xff1a;此处本人是将需要按照的软件存放在directory目录下&#xff0c;可根据实际情况调整接收路径。 命令如下&#xff1a; mkdir directory2.安装jdk 2.1 建…

vscode设置代码自动换行显示

☆ 问题描述 vscode设置代码自动换行显示 ★ 解决方案 ✅ 总结

深入理解mysql中的各种超时属性

1. 前言 connectTimeout: 连接超时 loginTimeout: 登录超时 socketTimeout: Socket网络超时&#xff0c;即读超时 queryTimeout: sql执行超时 transactionTimeout:spring事务超时 innodb_lock_wait_timeout:innodb锁等待超时 wait_timeout:非交互式连接关闭前的等待时间 inter…

TMC5160步进电机驱动芯片

TMC5160步进电机驱动芯片 特点和优势静止态自动降电流stealthChop2 & spreadCycle 驱动stealthChop2 & spreadCycle 驱动1.7 stallGuard2 – 机械负载传感1.8 coolStep –负载自适应电流控制1.9 dcStep –负载相关速度控制1.10 编码器接口 TMC5160工作模式模式 1&#…

wireshark 二次开发

一、 Windows 准备 1、源代码下载 Git&#xff1a;https://github.com/wireshark/wireshark 2、 准备Visual C 要编译wireshark&#xff0c;开发电脑上应该安装了Visual Studio并包括了Visual C&#xff0c;请至少安装Visual Studio 2010以减少不必要的麻烦。 visual studio …

Centos Stream 10 测试版下载:未来的RHEL10Rocky Linux 10

简介 最近发现Centos最放出了Stream 10 测试版本&#xff0c;应该是基于Fedora 40构建的。未来红帽会基于此版本构建RHEL 10。 内核版本&#xff1a;6.9.0 Python版本&#xff1a;3.12.2 RHEL系发行版对应关系 Fedora (根发行版-软件实时更新-只支持一年) >>某一版本作…

MySQL换路径(文件夹)

#MySQL作为免费数据库很受欢迎&#xff0c;即使公司没有使用&#xff0c;自己也可以用。它是一个服务&#xff0c;在点击CtrlAltDelete选择任务管理器后&#xff0c;它在服务那个归类里。 经常整理计算机磁盘分类的小伙伴&#xff0c;如果你们安装了MySQL&#xff0c;并且想移…

Docker的部署与基本使用

Docker的部署和基本使用 Docker是一个开源的容器化平台&#xff0c;它允许开发者将应用程序及其依赖项打包成独立的、可移植的容器&#xff0c;从而简化了应用程序的部署、管理和扩展过程。这些容器可以在任何支持Docker的平台上运行&#xff0c;确保了应用的一致性和可移植性…

pdf的压缩该怎么做?快速在线压缩pdf的方法

pdf文件是现在很常用的一种文件格式&#xff0c;有很多的文件内容都可以通过这种格式来展示内容&#xff0c;比如一些通知文件、设计图、个人信息等等&#xff0c;文件的内容越多就会越大&#xff0c;在使用的时候经常会受到一定的限制。那么有什么方法能够快速的将pdf文件变小…