【PGCCC】Postgresql 文件存储层

前言

在 postgresql 数据库里,数据都会以表的形式组织起来。表的数据会被持久化到底层的磁盘里。负责与底层的磁盘交互,就是 postgresql 的文件存储层。本篇博客会依次介绍表的文件构成、分片机制和存储接口。

表的文件类型

postgresql 使用 RelFileNode 来标识一张表

typedef struct RelFileNode
{
	Oid			spcNode;		/* tablespace */
	Oid			dbNode;			/* database */
	Oid			relNode;		/* relation */
} RelFileNode;

数据表都有下面三种文件

  1. main 文件存储着实际的数据,
  2. fsm 文件记录着 main 文件块的空闲大小,当有数据插入时,会优先从空闲位置写入。
  3. vm 文件记录了过期的数据,这在 vaccum 清洗过程中有用到。

ForkNumber 枚举定义文件类型

typedef enum ForkNumber
{
	InvalidForkNumber = -1,
	MAIN_FORKNUM = 0,  // 存储着实际的数据,文件名没有后缀
	FSM_FORKNUM,       // 存储着空闲位置,文件名的后缀为fsm
	VISIBILITYMAP_FORKNUM,  // 文件名的后缀为vm
	INIT_FORKNUM  // 用于数据库初始化,文件名的后缀为init
} ForkNumber;

#define MAX_FORKNUM		INIT_FORKNUM // 等于3

文件分片

因为有些文件系统对单个文件的数目大小有限制,postgresql 数据库为了良好的移植性,将上述文件进行切片,每个切片对应着一个文件,通过在文件名添加数字后缀来区分(注意第一个分片没有数字后缀)。每个文件切片由MdfdVec表示

typedef struct _MdfdVec
{
	File		mdfd_vfd;		// 文件描述符
	BlockNumber mdfd_segno;		// 分片索引
} MdfdVec;

块存储

postgresql 存储数据并不是一条一条的存储,而是将数据合并成一个小块,每个块的大小都相同,默认为8KB。之所以这样设计,是因为磁盘的读写速度太慢了,尤其是随机读写,通过增加单次的吞吐量,来提高读写性能。

每个块都有一个唯一的标识,叫做 block number。它们依次递增,连续的存储在文件里。每个文件分片包含的块数目是相同的。下面展示了根据 block number 找到对应的文件切片,

// blkno是块的唯一标识,RELSEG_SIZE是切片包含的块数目
targetseg = blkno / ((BlockNumber) RELSEG_SIZE);

动态哈希表

postgresql 使用 SMgrRelationData来表示单个表的文件结构,下面展示了主要成员

typedef struct SMgrRelationData
{
	RelFileNodeBackend smgr_rnode;	// 表的标识

	BlockNumber smgr_targblock; // 准备写的blocknum
	BlockNumber smgr_fsm_nblocks;	// 最大的fsm文件的fsm block number,用于快速判断用户传递的blocknum是否超过最大值,需要扩充
	BlockNumber smgr_vm_nblocks;	/* last known size of vm fork */

	int			smgr_which;		// 选择哪个存储接口,目前只有一种实现,默认为0
    
	int			md_num_open_segs[MAX_FORKNUM + 1];  // 每种类型文件的分片数目
	struct _MdfdVec *md_seg_fds[MAX_FORKNUM + 1];  // 每种类型对应的分片数组
} SMgrRelationData;

注意到和分片相关的两个数组md_num_open_segs和md_seg_fds,它们的数组长度都是文件类型的数目。前者是一个一维数组,表示打开的分片文件的数目。后者是一个二维数组,存储着每种类型文件的的分片 。

这里还额外说下RelFileNodeBackend的定义,它与RelFileNode的区别仅仅是多了一个BackendId

typedef struct RelFileNodeBackend
{
	RelFileNode node;<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值