
表空间
数据库在逻辑上分成多个存储单元,称作表空间。表空间用作把逻辑上相关的结构放在一起。数据库逻辑上是由一个或多个表空间组成。
-
逻辑关系存在表空间;
-
表空间存在对应的数据文件中;
新创建的数据库对应的数据文件的名称:
-
Catalog表空间:存放系统表信息 – databasename.dbf
-
System表空间:存放用户数据 – Udatabasename.dbf
-
Temp表空间 – Tdatabasename.dbf
1. 前面加 “U” 前缀代表用户数据表空间,用于保存用户表的数据。 2. 不带 U 代表 是系统表的表空间,用于保存系统表的数据。 3. U 前缀的数据文件代表的表空间名为PG。 4. 不带 U 的数据文件代表的表空间为 CATALOG。
数据文件结构

在 PostgreSQL 中,将保存在磁盘中的块称为 Page,而将内存中的块称为 Buffer,表和索引称为 Relation,行称为 Tuple。数据的读写是以 Page 为最小单位,每个 Page 默认大小为 8k,在编译 PostgreSQL 时指定的 BLCKSZ 大小决定 Page 的大小。每个表文件由多个 BLCKSZ 字节大小的 Page 组成,每个 Page 包含若干 Tuple。
Page
将数据文件中的空间从逻辑上划分成一个个页面(数据块)。页面是数据库I/O的基本单位,即只能整页读写数据文件, 页面的大小默认是8K。
PageHeader
PageHeader 描述了一个数据页的页头信息,包含页的一些元信息。

-
pg_lsn:在 ARIES Recovery Algorithm 的解释中,这个 lsn 称为 PageLSN,它确定和记录了最后更改此页的 xlog 记录的 LSN,把数据页和 WAL 日志关联,用于恢复数据时校验日志文件和数据文件的一致性;pd_lsn 的高位为 xlogid,低位记录偏移量;因为历史的原因,64 位的 LSN 保存为两个 32 位的值。
-
pg_flags:标识页面的数据存储情况。
-
pd_special:指向索引相关数据的开始位置,该项在数据文件中为空,主要是针对不同索引。
-
pd_lower:指向空闲空间的起始位置。
-
pd_upper:指向空闲空间的结束为止
-
pd_pagesize_version:不同的 PostgreSQL 版本的页的格式可能会不同。
-
pd_linp[1]:行指针数组,这些地址指向 Tuple 的存储位置
如果一个表由一个只包含一个堆元组的页面组成。该页面的 pd_lower 指向第一行指针,并且行指针和 pd_upper 都指向第一个堆元组。当第二个元组被插入时,它被放置在第一个元组之后。第二行指针被压入第一行,并指向第二个元组。pd_lower 更改为指向第二行指针,pd_upper 更改为第二个堆元组。此页面中的其他头数据也被重写为适当的值
PageData
-
Data 段中,包含有: ItemIdData 段,Free Space段, Items段 以及Special space段。
-
ItemIdData 段: Array of (offset,length) pairs pointing to the actual items. 4 bytes per item.
-
Free Space 段:The unallocated space. New item pointers are allocated from the start of this area, new items from the end.
-
Items 段: The actual items themselves.
-
Special space 段: Index access method specific data. Different methods store different data. Empty in ordinary tables.
-
Item 的存储是从 pg_upper 向 pg_lower(类似堆)方向增长。ItenIdData 的存储是从 pg_lower 向 pg_upper 方向增长(类似栈)。
PageTuple
每个 Tuple 包含两部分的内容,一部分为 HeapTupleHeader,用来保存 Tuple 的元信息,包含该 Tuple 的 OID、xmin、cmin 等;另一部分为 HeapTuple,用来保存 Tuple 的数据。

Extent(区)
把数据文件中 8 个连续的 Page 构成的空间称为一个 Extent。Extent 是数据库进行数据文件空间分配/释放的基本单位。每个表、索引、序列对象都是由若干个区组成。数据文件被创建后,除自动保留部分区作为控制区外,其他区全部处于未分配状态。表、索引、序列对象的所有数据都存放在 Extent 中,当向这些 Extent 中插入数据时,若该 Extent 的所有页面都已占满,系统就会自动在所属表空间的数据文件中寻找一个尚未分配的区,并将其状态修改为数据区。
控制页面
-
用于空间管理的控制页面:PFS/GAM/IAM。
-
用于增量备份的控制页面:DCM。
-
判断可见性的控制页面:VM。
-
预留的控制页面:BCM/SGAM。
PFS
Page Free Space,简称 PFS 页.
-
功能:用于记录本数据文件中页面的空间使用情况。对文件中的每个页面,PFS中都有一个“字节”与之对应,该字节记录了该页面的状态。
-
每个页面可能有三种状态
-
RFS_FREE:该页面已被物理分配,但尚未分配给任何数据对象或控制页;
-
PFS_DATA:该对象被分配作为数据页使用;
-
PFS_CTRL:该对象被分配作为控制页使用;
-
PFS 页前 64 bytes 被预留为页头, 剩下 81024 - 64 = 8128 一共覆盖 81288 K = 64 MB 空间。故 PFS 页每隔 8128 个页面出现一次,系统初始化把第一个 PFS 页放在数据文件的第二个页面位置,即:第1号数据页面,由此可知,第 N 个 PFS 页的位置在8128*N+1。
GAM
Global Allocation Map,简称 GAM 页。
-
功能:记录所在数据文件的 Extent 的分配情况,GAM 页中除 GAM 头外,剩下空间的每一位(bit)均对应一个 Extent 的分配情况。若某 bit 位为 1,则表明该 bit 位所关联的 Extent 已被分配出去,反之未被分配。
-
若一个 GAM 页面大小为 8K,则除 GAM 头(64 bytes)外,一个 GAM 页面所能覆盖的文件范围是:(81024-64)8(88K),约 4GB 空间。此外,GAM 页每隔 881288 个页面出现一个,系统要求第一个GAM 页出现在文件的第 3 个页面位置(即:第 2 个索引位置),由此得知,第N个GAM 页的出现位置是:881288*N+2
IAM
Index Allocation Map,简称 IAM 页。
-
功能:每个 IAM 页只隶属于一个数据库对象(例如:表),但一个数据库对象可包含多个 IAM 页,由此可见 IAM 页与数据库对象的关系是 1 对 1,而数据库对象与 IAM 页的关系是 1 对多.
-
IAM 的结构与 GAM 页类似,除 IAM 头外,剩下空间的每一位 (bit) 均对应着一个与 IAM 相关的 Extent。若某 bit 位为 1,则表明该 bit 位所关联的 Extent 已被分配给该 IAM,反之未被分配。若一个IAM页面大小为 8K,则除 IAM 头(64 bytes) 外,一个 IAM 页面所能覆盖的文件范围是: (81024-64)8(88K),约4 GB 空间。但与 GAM 也不同之处在于:IAM 的出现位置不固定,只在在创建数据库对象的时候才分配。

该博客由自己根据自身阅读习惯,整理各方大神总结内容所得,如有冒犯,还望见谅,非常感谢!!!