张大妈

PostgreSQL源码:存储引擎3|Insert | PG数据插入底层原理

源自UP主:Socrates0010

01-25 20:13

想深入了解PostgreSQL的存储机制吗?通过剖析`INSERT`语句的底层实现,可以清晰揭示数据在页面中的物理布局和变化过程。这份内容将源码分析与页面结构图解相结合,帮助理解从执行SQL语句到数据物理写入的完整链路,是掌握PG存储引擎的关键一步。

PostgreSQL源码:存储引擎3|Insert | PG数据插入底层原理智能速览

  • 插入数据前,页面的pd_lower和pd_upper初始值分别为24和8192。

  • 数据从页面尾部向上插入,而记录其位置的ItemId从头部向下插入。

  • 插入一条数据后,pd_lower变为28,pd_upper变为8160。

  • ItemIdData结构体存储了元组的偏移量、长度和状态信息。

  • 核心函数PageAddItemExtended处理了字节对齐、数据拷贝和页头更新等操作。

PostgreSQL源码:存储引擎3|Insert | PG数据插入底层原理精华内容

一条简单的`INSERT`语句,背后隐藏着复杂的内存管理和数据布局逻辑。下面将通过追踪源码与解析页面结构,详细拆解PostgreSQL是如何将一条记录存入页面中的。

页面的初始状态

一个空的PostgreSQL页面,默认大小为8KB(即8192字节)。页面最开始的24字节是固定的页面头部(PageHeaderData),用于存储页面的元信息。

因此,在插入任何数据之前,表示空闲空间起始位置的`pd_lower`为24,而表示结束位置的`pd_upper`则为8192。此时,从24到8192之间的全部空间都是可供使用的`free space`。

数据插入过程

当执行`INSERT INTO tb VALUES(1)`时,PostgreSQL会进行双向操作。首先,它将待插入的元组数据从页面的尾部(即`pd_upper`方向)插入。这个元组本身包含头信息和数据,共28字节,但为了内存对齐(通常是8字节),实际会占用32字节的空间。

因此,页面的`pd_upper`从8192减少到8160。与此同时,在页头的`pd_lower`位置,系统会插入一个4字节的`ItemId`(也称为`line pointer`),用于指向刚刚插入的元组。这个操作使得`pd_lower`从24增加到28。

关键结构ItemId

`ItemId`是理解页面布局的核心,其结构体`ItemIdData`包含三个关键字段。`lp_off`占15位,记录元组在页面内的偏移量,本例中为8160;`lp_flags`占2位,标记元组状态,如`LP_NORMAL`表示正常状态;`lp_len`同样占15位,记录元组的实际长度,即28字节。

通过这个指针数组,PostgreSQL能够快速定位和管理页面内的每一条记录,而无需扫描整个页面。

源码级实现

在源码层面,上述过程主要由`PageAddItemExtended`函数实现。该函数首先通过`MAXALIGN`宏对元组大小进行对齐处理,确保其占32字节。接着,它会更新页面头部的`pd_upper`,为新元组预留空间。

然后,函数设置`ItemId`的`lp_off`和`lp_len`等字段。最后,通过`memcpy`函数,将元组数据精确拷贝到`pd_upper`指定的位置,并更新`pd_lower`的值,为下一次插入做好准备。整个流程体现了PG在存储管理上的严谨设计。

通过源码和页面结构的双重解析,`INSERT`操作的神秘面纱被揭开。理解了数据如何在页面中安家,就为后续学习MVCC、更新优化等更高级的主题打下了坚实基础。PostgreSQL还有哪些值得探索的底层设计呢?

内容由AI生成
0
扫一下,分享更方便,购买更轻松
0评论

当前文章无评论,是时候发表评论了
提示信息

取消
确认
评论举报

最新文章 热门文章