PgSQL-内核特性-TupleTableSlotOps

PgSQL-内核特性-TupleTableSlotOps

执行器中表达式结果、函数结果、投影结果等,各种结果都需要以元组的形式返回,所以PgSQL引入了一种通用格式保存数据:TupleTableSlot。PgSQL执行器将记录存储到“元组表”中在各个算子之间进行传递,元组表是独立TupleTableSlot的链表。而TupleTableSlot又分为多种,以减少解析和构建开销。

1、介绍

存储模块提供了元组(HeapTuple)的定义和操作接口,但这些接口针对物理元组,解析和构造开销比较大,不能满足执行器对性能要求。执行器在进行投影和选择操作时,需要快速获取元组属性;缓存元组时又希望元组尽可能小,以节省空间。所以PgSQL定义了多种TupleTableSlotOps。

1.1 内置的slot类型

按照分配的成员函数TupleTableSlotOps进行区分:

1)磁盘缓冲页的物理元组(TTSOpsBufferHeapTuple)

2)在分配的内存中构造的物理元组(TTSOpsHeapTuple)

3)在分配的内存中构造的“最小化”物理元组(TTSOpsMinimalTuple)

4)由Datum/isnull数组组成的“虚拟”元组(TTSOpsVirtual)

说明

1)前面两个都是处理“物化”的元组,只是资源管理方式不同。

2)对于磁盘页上的元组,需要pin住对应的buffer,直到TupleTableSlot上元组的引用被删除

3)对于分配的内存中的元组,通常在TupleTableSlot上元组的引用被删除时释放内存。

4)对于“最小化”的元组,处理方式与分配的内存中的元组类似。目前最小化元组不会存储在缓冲区上,并且没有“系统列”,实际上有OID,但是我们不需要访问。

5)“虚拟”元组是一种优化,以最小化计划节点之间物理数据拷贝。“虚拟”元组只有values和NULL的bitmap组成的虚拟元组。Slot中指向存储的Datums指针和TupleTableSlot直接关联,直到物化后才会关联。通常情况下指向子节点返回输出TupleTableSlot的元组存储部分,或者函数在执行计划节点的per-tuple econtext中构建的结果。执行计划节点确保“虚拟”元组只有非法或者不是物化的时候才释放资源。需要注意,“虚拟”元组没有任何系统列。

6)TupleTableSlot中的Datum/isnull数组有双重作用:对于“虚拟”slots,这就是全部的数据,其他类型的slot需要从tuple中提取。(注意,物理元组的values的里面有很多传引用的值,真正的值记录在物理元组中,这里只是记录了引用指针)

7)TupleTableSlot中的tts_flags标签TTS_FLAG_EMPTY时表示该slot为空,即没有实际元组值。TTS_FLAG_EMPTY是新创建slot还没分配tuple描述符的唯一状态。这种状态下不能设置TTS_SHOULDFREE标记,tts_tuple必须为NULL ,tts_nvalid必须是0。SHOULDFREE设置后,物理tuple被slot拥有,当slot的引用删除后,需要释放。

8)tupleDescriptor 只是由 TupleTableSlot 代码引用,而不是复制。 ExecSetSlotDescriptor() 的调用者负责提供一个描述符,该描述符的生命周期必须与slot一样长。

1.2 TupleTableSlot结构

/* base tuple table slot type */
typedef struct TupleTableSlot
{NodeTag    type;
#define FIELDNO_TUPLETABLESLOT_FLAGS 1uint16    tts_flags;    /* Boolean states */
#define FIELDNO_TUPLETABLESLOT_NVALID 2AttrNumber  tts_nvalid;    /* # of valid values in tts_values */const TupleTableSlotOps *const tts_ops; /* implementation of slot */
#define FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR 4TupleDesc  tts_tupleDescriptor;  /* slot's tuple descriptor */
#define FIELDNO_TUPLETABLESLOT_VALUES 5Datum     *tts_values;    /* current per-attribute values */
#define FIELDNO_TUPLETABLESLOT_ISNULL 6bool     *tts_isnull;    /* current per-attribute isnull flags */MemoryContext tts_mcxt;    /* slot itself is in this context */ItemPointerData tts_tid;  /* stored tuple's tid */Oid      tts_tableOid;  /* table oid of tuple */
} TupleTableSlot;

1.3 TupleTableSlotOps类型关系

fd5d8fe357bfb54ed84ce2819998a07f.png

这四种基本都是从TupleTableSlot衍生而来。

2、以SeqScan算子为例

8982befa7176e95c9d552380746e3746.png

ExecInitSeqScan初始化了两个TupleTableSlot:ss_ScanTupleSlot和ps_ResultTupleSlot。分别用于保存从存储扫描上来的记录和投影的结果。其中ss_ScanTupleSlot为TTSOPSBufferHeapTuple类型,ps_ResultTupleSlot为TTSOpsVirtual类型。

b31776e74d9a79fe37d625aa87936cd7.png

我们看下算子的执行。首先需要从底层存储读取记录:

1)ExecSeqScan->SeqNext从底层读取记录,可以看到物理页上的记录通过指针保存到HeapTuple

2)HeapTuple通过tts_buffer_heap_store_tuple函数保存到BufferHeapTupleTableSlot的base.tuple中

3)返回的是BufferHeapTupleTableSlot,作为TupleTableSlot地址转换后返回

接着再看下投影操作:

1)其实是BufferHeapTupleTableSlot放到econtext->ecxt_scantuple,然后进行表达式计算(投影操作通过表达式计算完成)

2)投影结果保存到ps_ResultTupleSlot中,他是TTSOpsVirtual类型。

3)由此从底层存储的TTSOPSBufferHeapTuple转换成TTSOpsVirtual类型。

3、总结

9b83587566e780796456be482cbdec7a.png

四种类型关系如上图所示。

1)TupleTableSlot本身带了tts_values、tts_isnull能存数据。

2)TupleTableSlot的衍生结构【HeapTupleTableSlot】多了个物理tuple的指针,能挂一个物理tuple,用的时候解开到tts_values、tts_isnull中。

3)HeapTupleTableSlot的衍生结构【BufferHeapTupleTableSlot】又多了个buffer,他会和buffer关联起来,释放或materialize后时候需要把buffer释放掉。

4)TupleTableSlot的衍生结构【MinimalTupleTableSlot】在基类的基础上了记录了物理元组tuple和mintuple,mintuple表示物理元组去掉HeapTuple头和HeapTupleHeader头之后剩下的部分:isnull/dataums,纯数据部分。

5)TupleTableSlot的衍生结构【VirtualTupleTableSlot】就比较简单的了,只多了个char *data,用于记录任何数据,可以满足各种场景的需求。

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

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

相关文章

【神经网络可视化】 梯度上升,可视化工具,风格转移

可视化可以帮助我们更好的理解卷积网络每一层学到了什么,或者说每一个卷积核究竟学到了什么,他是怎么理解图像的 这种的话当我们神经网络结果不太好时,我们可以分析不好的原因 图片来源于李飞飞老师的内容 梯度上升方法做可视化 文章目录 …

BUUCTF reverse wp 21 - 30

[ACTF新生赛2020]rome 无壳, 直接拖进IDA32 y键把v2改成char[49], n键重命名为iuput int func() {int result; // eaxint v1[4]; // [esp14h] [ebp-44h]char input[49]; // [esp24h] [ebp-34h] BYREFstrcpy(&input[23], "Qsw3sj_lz4_Ujwl");printf("Please…

力扣 -- 44. 通配符匹配

解题步骤&#xff1a; 参考代码&#xff1a; class Solution { public:bool isMatch(string s, string p) {int ms.size();int np.size();//为了调整映射关系s s;p p;//多开一行多开一列vector<vector<bool>> dp(m1,vector<bool>(n1,false));//初始化//dp[0]…

Mysql——三、SQL语句(上篇)

Mysql 一、SQL语句基础1、SQL简介2、SQL语句分类3、SQL语句的书写规范 二、数据库操作三、MySQL 字符集1、变量2、utf8和utf8mb4的区别 四、数据库对象五、SELECT语句1、简单的SELECT语句2、SQL函数2.1 聚合函数2.2 数值型函数2.3 字符串函数2.4 日期和时间函数2.5 流程控制函数…

JAVA:实现Excel和PDF上下标

1、简介 最近项目需要实现26个小写字母的上下标功能,自己去网上找了所有Unicode的上下标形式,缺少一些关键字母,顾后面考虑自己创建上下标字体样式,以此来记录。 2、Excel Excel本身是支持上下标,我们可以通过Excel单元格的样式来设置当前字体上下标,因使用的是POI的m…

Object.defineProperty()方法详解,了解vue2的数据代理

假期第一篇&#xff0c;对于基础的知识点&#xff0c;我感觉自己还是很薄弱的。 趁着假期&#xff0c;再去复习一遍 Object.defineProperty(),对于这个方法&#xff0c;更多的还是停留在面试的时候&#xff0c;面试官问你vue2和vue3区别的时候&#xff0c;不免要提一提这个方法…

【知识点】JavaScript中require的一些理解

以下内容源自个人理解&#xff0c;若有错误欢迎指出。 猜想 多个文件中require同一个文件时&#xff0c;对于首次出现的require&#xff0c;会去读取文件并执行一遍&#xff0c;然后加入缓存&#xff1b;之后当再次require到这个文件时&#xff0c;只会指向这个缓存&#xff0c…

Django(21):使用Celery任务框架

目录 Celery介绍Celery安装Celery使用项目文件和配置启动Celery编写任务调用异步任务查看任务执行状态及结果 设置定时和周期性任务配置文件添加任务Django Admin添加周期性任务启动任务调度器beat Flower监控任务执行状态Celery高级用法与注意事项给任务设置最大重试次数不同任…

px4的gazebo仿真相机模型报错解决办法,返回值256

&#x1f449;事情起因&#xff1a;我想做关于PX4无人机的摄像头仿真&#xff0c;根据PX4的官网文件 Tools/sitl_gazebo文件夹里面有对应的模型可以使用&#xff0c;我就想在mavros_posix_sitl文件里面修改vehicle参数&#xff0c;比如直接将vehicle“iris_stereo_camera”。然…

PyTorch 模型性能分析和优化 — 第 1 部分

一、说明 这篇文章的重点将是GPU上的PyTorch培训。更具体地说&#xff0c;我们将专注于 PyTorch 的内置性能分析器 PyTorch Profiler&#xff0c;以及查看其结果的方法之一&#xff0c;即 PyTorch Profiler TensorBoard 插件。 二、深度框架 训练深度学习模型&#xff0c;尤其是…

Springboot中使用拦截器、过滤器、监听器

一、Servlet、Filter&#xff08;过滤器&#xff09;、 Listener&#xff08;监听器&#xff09;、Interceptor&#xff08;拦截器&#xff09; Javaweb三大组件&#xff1a;servlet、Filter&#xff08;过滤器&#xff09;、 Listener&#xff08;监听器&#xff09; Spring…

嵌入式Linux应用开发-面向对象-分层-分离及总线驱动模型

嵌入式Linux应用开发-面向对象-分层-分离及总线驱动模型 第八章 驱动设计的思想&#xff1a;面向对象/分层/分离8.1 面向对象8.2 分层8.3 分离8.4 写示例代码8.5 课后作业 第九章 驱动进化之路&#xff1a;总线设备驱动模型9.1 驱动编写的 3种方法9.1.1 传统写法9.1.2 总线设备…

QT信号槽

目录 信号槽的概念 按钮的常用信号 自定义槽函数 自定义信号函数 自定义槽和信号注意的事项 信号与槽的拓展 lambda表达式 信号槽的概念 信号槽是Qt框架引以为豪的机制之一。所谓信号槽&#xff0c;实际就是观察者模式。当某个事件发生之后&#xff0c;比如&#xff0c…

布隆过滤器Bloom Filter

本章代码gitee仓库&#xff1a;布隆过滤器 文章目录 0. 前言1. 布隆过滤器的概念2. 布隆过滤器的实现2.1 哈希函数2.2 插入和判断 3. 布隆过滤器的删除4. 布隆过滤器的误判 0. 前言 我们在玩某款游戏的时候&#xff0c;刚注册的话&#xff0c;我们需要取一个昵称&#xff0c;这…

【Java】复制数组的四种方式

1. System.arraycopy() 用来将一个数组的&#xff08;一部分&#xff09;内容复制到另一个数组里面去。 定义&#xff1a; void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);例&#xff1a; int[] arr1 { 1, 2, 3, 4, 5 }; int[] arr2 new…

CSS详细基础(四)显示模式

本帖开始介绍CSS中更复杂的内容 目录 一.显示模式 1.行内元素 2.块级元素 3.行内块元素 二.背景样式 一.显示模式 顾名思义&#xff0c;在CSS中&#xff0c;元素主要有3种显示模式&#xff1a;行内元素、块级元素、行内块元素~ 所谓块级元素&#xff0c;指的是该元素在…

ROS2 从头开始​​:第6部分 - ROS2 中的 DDS,用于可靠的机器人通信

一、说明 在这篇文章中,我们将重点关注 ROS 2的通信栈DDS,其中这是介于管理节点通信与控制节点通信环节,是上位机决策体系与下位机的控制体系实现指令-执行-反馈的关键实现机制。 二、ROS工程的概念框架 现代机器人系统非常复杂,因为需要集成各种类型的传感器、执行器和其…

Vue封装全局SVG组件

1.SVG图标配置 1.安装插件 npm install vite-plugin-svg-icons -D 2.Vite.config.ts中配置 import { createSvgIconsPlugin } from vite-plugin-svg-icons import path from path export default () > {return {plugins: [createSvgIconsPlugin({// Specify the icon fo…

JavaScript高阶班之ES6 → ES11(八)

JavaScript高阶班之ES6 → ES11 1、ES6新特性1.1、let 关键字1.2、const关键字1.3、变量的解构赋值1.3.1、数组的解构赋值1.3.2、对象的解构赋值 1.4、模板字符串1.5、简化对象写法1.6、箭头函数1.7、函数参数默认值1.8、rest参数1.9、spread扩展运算符1.9.1、数组合并1.9.2、数…

PYQT制作动态时钟

所有代码&#xff1a; import sys from PyQt5.QtCore import Qt, QTimer, QRect from PyQt5.QtGui import QPixmap, QTransform, QPainter, QImage from PyQt5.QtWidgets import QApplication, QLabel from PyQt5 import uic import newdef adder():global iglobal angle_s, a…