PostgreSQL技术内幕8:PostgreSQL查询执行器

2024-09-03 21:28

本文主要是介绍PostgreSQL技术内幕8:PostgreSQL查询执行器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

0.简介

执行器是查询编译和存储引擎之间的连接模块,其负责将优化器输出的执行计划,进行初始化、执行,访问存储引擎并获得最终结果返回,本章主要介绍PG的执行器模型和其执行流程。

执行器的处理模型

常见的执行器的处理模型包含基于拉操作的Pull模型和基于推操作的Push模型。

1.1 火山模型(Pull模型)

火山模型也叫迭代器模型,最早是《Volcano, an Extensible and Parallel Query Evaluation System》中提出,其产生的背景是当时的 IO 速度是远远小于 CPU 的计算速度的,所以降低虚函数开销带来的优化微乎其微,且内存空间有限,单个处理更附和当时的场景。火山模型是由上游节点主动pull来驱动下层节点,逐层调用来实现数据的处理。其优缺点也比较明确:
优点:
1)实现简单,通用性好:每个Operator都可以独立实现,不受其他Operator的影响,且不受数据规模限制,可以处理任意规模的数据集。
2)灵活性高:可以灵活控制输出的数量,比如Limit算子及时短路。
缺点:
1)虚函数开销:每次调用GetNext获取一个tuple,会产生大量虚函数调用开销。
2)对应Cache不友好:过多的控制语句和函数调用容易导致缓存失效。

在这里插入图片描述

1.2 Push模型

可以看到,Push模型和Pull模型刚好相反,是从底层元组主动向上传递从而驱动整个流程。Push模型在计划的叶子节点开始执行,每层执行完成后物化然后传递给上一层节点。

在这里插入图片描述

优点:
1)减少函数调用:与Pull模型相比,Push模型显著减少了函数调用次数。
2)Cache命中率高:由于内部处理逻辑一致,Cache命中率得到显著提升。
缺点:
1)内存占用较大:由于每个节点都需要物化处理后的数据,可能导致内存占用升高。

1.3 向量化执行引擎

可以看到,把pull模型一次获取一条改为一个循环,处理完再向上驱动即为Push模型。向量化是对其另一种优化,一次处理一批数据,减少函数调用次数和缓存切换频率,提高执行效率。同时,结合了列式存储和SIMD指令,提高执行器性能。

2. PG执行器

执行器是执行计划和存储引擎之间的关联模块,那么接下来就分别从执行器流程、与执行计划的关联、与存储引擎的关联来进行执行器的分析。

2.1 执行器本身流程

在PG中有四个个用于调用执行器的接口,他们是ExecutorStart、ExecutorRun、ExecutorFinish和ExecutorEnd。其职责如下:

1)ExecutorStart:主要负责初始化各个算子的状态,通过调用standard_ExecutorStart对执行器进行必要的初始化

2)ExecutorRun:执行器运行阶段,通过ExecutorRun来执行算子。

3)ExecutorFinish:统计信息收集和清理。

4)ExecutorEnd:逐层结束下游节点的执行,释放资源。

顺序关系即为:ExecutorStart --> ExecutorRun --> ExecutorFinish -->ExecutorEnd

2.2 执行器与执行计划的关联

与传统执行器直接关联执行计划不同,PG引入了Portal层,负责将查询计划转发,同时根据策略生成路径,其结构如下:

typedef struct PortalData
{/* Bookkeeping data */const char *name;      /* portal's name */const char *prepStmtName;  /* source prepared statement (NULL if none) */MemoryContext portalContext;  /* subsidiary memory for portal */ResourceOwner resowner;    /* resources owned by portal */void    (*cleanup) (Portal portal); /* cleanup hook */....    /* other */
}      PortalData;

Portal提供了三个方法:PortalStart、PortalRun和PortalDrop。
1)PortalStart:初始化Portal参数和策略。
2)PortalRun:根据语句类型选择执行器路径,返回结果。
3)PortalDrop:结束执行器,释放资源。

2.3 执行器和存储引擎的关联

以一个简单的Scan为例,顺序扫描的入口函数为SeqNext,其会调用heap_getnext,heap_getnext内部调用heapgettup,其内部使用就是共享内存和页面对应的部分。

这篇关于PostgreSQL技术内幕8:PostgreSQL查询执行器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1134091

相关文章

Java利用JSONPath操作JSON数据的技术指南

《Java利用JSONPath操作JSON数据的技术指南》JSONPath是一种强大的工具,用于查询和操作JSON数据,类似于SQL的语法,它为处理复杂的JSON数据结构提供了简单且高效... 目录1、简述2、什么是 jsONPath?3、Java 示例3.1 基本查询3.2 过滤查询3.3 递归搜索3.4

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

浅谈mysql的sql_mode可能会限制你的查询

《浅谈mysql的sql_mode可能会限制你的查询》本文主要介绍了浅谈mysql的sql_mode可能会限制你的查询,这个问题主要说明的是,我们写的sql查询语句违背了聚合函数groupby的规则... 目录场景:问题描述原因分析:解决方案:第一种:修改后,只有当前生效,若是mysql服务重启,就会失效;

MySQL多列IN查询的实现

《MySQL多列IN查询的实现》多列IN查询是一种强大的筛选工具,它允许通过多字段组合快速过滤数据,本文主要介绍了MySQL多列IN查询的实现,具有一定的参考价值,感兴趣的可以了解一下... 目录一、基础语法:多列 IN 的两种写法1. 直接值列表2. 子查询二、对比传统 OR 的写法三、性能分析与优化1.

mybatis-plus 实现查询表名动态修改的示例代码

《mybatis-plus实现查询表名动态修改的示例代码》通过MyBatis-Plus实现表名的动态替换,根据配置或入参选择不同的表,本文主要介绍了mybatis-plus实现查询表名动态修改的示... 目录实现数据库初始化依赖包配置读取类设置 myBATis-plus 插件测试通过 mybatis-plu

MySQL中实现多表查询的操作方法(配sql+实操图+案例巩固 通俗易懂版)

《MySQL中实现多表查询的操作方法(配sql+实操图+案例巩固通俗易懂版)》本文主要讲解了MySQL中的多表查询,包括子查询、笛卡尔积、自连接、多表查询的实现方法以及多列子查询等,通过实际例子和操... 目录复合查询1. 回顾查询基本操作group by 分组having1. 显示部门号为10的部门名,员

mysql关联查询速度慢的问题及解决

《mysql关联查询速度慢的问题及解决》:本文主要介绍mysql关联查询速度慢的问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录mysql关联查询速度慢1. 记录原因1.1 在一次线上的服务中1.2 最终发现2. 解决方案3. 具体操作总结mysql

mysql线上查询之前要性能调优的技巧及示例

《mysql线上查询之前要性能调优的技巧及示例》文章介绍了查询优化的几种方法,包括使用索引、避免不必要的列和行、有效的JOIN策略、子查询和派生表的优化、查询提示和优化器提示等,这些方法可以帮助提高数... 目录避免不必要的列和行使用有效的JOIN策略使用子查询和派生表时要小心使用查询提示和优化器提示其他常

Ubuntu 22.04 服务器安装部署(nginx+postgresql)

《Ubuntu22.04服务器安装部署(nginx+postgresql)》Ubuntu22.04LTS是迄今为止最好的Ubuntu版本之一,很多linux的应用服务器都是选择的这个版本... 目录是什么让 Ubuntu 22.04 LTS 变得安全?更新了安全包linux 内核改进一、部署环境二、安装系统

SQL 中多表查询的常见连接方式详解

《SQL中多表查询的常见连接方式详解》本文介绍SQL中多表查询的常见连接方式,包括内连接(INNERJOIN)、左连接(LEFTJOIN)、右连接(RIGHTJOIN)、全外连接(FULLOUTER... 目录一、连接类型图表(ASCII 形式)二、前置代码(创建示例表)三、连接方式代码示例1. 内连接(I