PgSQL-内核特性-TupleTableSlotOps

news/2024/10/18 8:34:16/

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.ppmy.cn/news/1132005.html

相关文章

剖析华为云Astro Platform技术价值与使用体验

面对企业IT专业人员紧缺的挑战,华为云Astro低代码平台提供创新解决方案。让非编程专业人士能快速构建、部署应用,缓解开发资源压力,并高度整合技术架构,强化项目沟通协作。使每个参与其中的角色都找到自己的位置,携手全…

工信部:杭州亚运会开幕式首创 5G 超密组网方案,场馆网络无缝覆盖

“工信 V 报”今日发布消息称,工信部经过精心统筹、周密部署,举全系统之力圆满完成了杭州亚运会开幕式各项保障任务。 据介绍,亚运会的指挥调度、安全保卫、通信网络、计时记分、电视转播等系统顺畅运行,对无线电安全、信息通信服…

Hello World!1分钟配置好你的Go环境

目录 一、简介为什么选择Golang?Golang与其他语言的对比核心特性应用场景社区和生态系统性能标准企业级应用 二、环境要求操作系统WindowsLinux/UnixmacOS 硬件需求其他依赖软件异常情况和处理方法 三、下载和安装GolangWindows系统使用官方安装包使用Chocolatey&am…

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

一、Servlet、Filter(过滤器)、 Listener(监听器)、Interceptor(拦截器) Javaweb三大组件:servlet、Filter(过滤器)、 Listener(监听器) Spring…

编程每日一练(多语言实现)基础篇:求总数问题

文章目录 一、实例描述二、技术要点三、代码实现3.1 C 语言实现3.2 Python 语言实现3.3 Java 语言实现3.4 JavaScript 语言实现 一、实例描述 集邮爱好者把所有的邮票存放在三个集邮册中,在A册内存放全部的十分之二,在B册内存放不知道是全部的七分之几&…

asp.net core mvc 视图组件viewComponents

ASP.NET Core MVC 视图组件(View Components)是一种可重用的 UI 组件,用于在视图中呈现某些特定的功能块,例如导航菜单、侧边栏、用户信息等。视图组件提供了一种将视图逻辑与控制器解耦的方式,使视图能够更加灵活、可…

Go 之 redis 处理

Redis是一个开源的内存数据库,支持诸如字符串(string)、哈希(hashe)、列表(list)、集合(set)、带范围查询的排序集合(sorted set)、bitmap、hyper…

产品设计与用户体验 优漫动游

用户体验是指产品在运行过程中与用户产生的联系以及用户在使用过程中的主观感受;产品在设计并生产的过程中,哪些会影响用户的体验,以及如何围绕以用户为中心进行产品设计,在《用户体验要素》一书中提出了用户体验五要素的理念&…