PHP实战中知识总结 / PgSQL - 数据文件的内部结构

一、数据文件内部结构

在数据文件内部(堆表和索引,以及空闲空间映射和可见性映射),它被分成固定长度的页(或块),默认为8192字节(8 KB)。 每个文件中的那些页从 0 开始按顺序编号,这样的编号称为块编号。 如果文件已被填满,PostgreSQL 会在文件末尾添加一个新的空页以增加文件大小。

表中的页面包含三种数据:

(1)heap tuples: 行数据

(2)line pointers: 行指针,指向对应的tuple,offffset number从1开始

(3)header data:

pd_lsn :保存此page的最新的WAL记录的lsn,用于数据恢复的

pd_lower :指向最新的line pointer

pd_upper: 指向最新的tuple

pd_checksum:此变量存储此页面的校验和值。

pd_special:此变量用于索引。 在表格内的页面中,它指向页面的末尾。 (在索引内页中,它指向特殊空间的开始,即只由索引保存的数据区,根据B-tree、GiST、GiN等索引类型包含特定数据。)

二、写操作

假设一个表由一页组成,其中只包含一个堆元组。 本页的pd_lower指向第一行指针,行指针和pd_upper都指向第一个堆元组。 见图 (a)。

当插入第二个元组时,它被放置在第一个元组之后。 第二行指针被推到第一行指针上,它指向第二个元组。 pd_lower 更改为指向第二行指针,pd_upper 更改为指向第二个堆元组。 见图 (b)。 此页中的其他头数据(例如,pd_lsn、pg_checksum、pg_flag)也被重写为适当的值

三、读操作

(1)sequential scan:遍历所有的pages的line pointers获取所有的tuples;

(2)index scan:通过索引获取tids,然后再根据tids获取tuples;

(3)index only scan:一般来说只扫描索引就能获取需要的字段,不需要回表读,需要VM配合使用;

(4)bitmap index scan:当index scan命中大量的rows时,将会构造一个page的bitmap(一个bit对应一个 page),然后在recheck每个page找到符合条件的rows,这样可以避免重复扫描page;

PHP实战中知识总结