PostgreSQL是如何存储数据的?存储结构浅析

2022-06-3011:53:24数据库教程Comments1,060 views字数 2321阅读模式

PostgreSQL 数据库是功能强大的开源数据库,越来越多的公司开始使用 PostgreSQL。存储系统是 PostgreSQL 的最底层模块,它向下通过操作系统接口访问物理数据,向上为上层模块提供存储操作的接口和函数。本文通过对 PostgreSQL 的存储结构进行浅析,帮助大家了解这一强大的关系型数据库是如何存储数据的。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

 文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

- 数据目录 -

PostgreSQL 安装完成后必须先使用 initdb 程序初始化磁盘上的数据存储区,生成模板数据库和相应的目录、文件信息。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

initdb -D /usr/local/pgsql/data文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

初始化目录中包含数据文件、参数文件、控制文件、数据库运行日志及 WAL 日志文件等,下图各目录和子文件的用途在此不做赘述。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

PostgreSQL是如何存储数据的?存储结构浅析文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

默认情况下,PostgreSQL 中的所有数据都存储在其数据目录里,这个数据目录通常会用环境变量 PGDATA 来引用,对于某个具体的数据库,在 PGDATA/base 里都对应有一个子目录,子目录的名字是该数据库在系统表 pg_database 里的 OID,每个表的数据都存在其所属数据库目录下的独立文件里,文件以该表的 filenode 号命名,为了避免有些文件系统不支持大文件,PostgreSQL 限制表文件大小不能超过 1GB(默认 1GB,编译时可通过./configure --with-segsize= x 修改)因此,当表文件超过 1GB 时,会另建一个有尾缀的文件 relfilenode.1,relfilenode.2…… 以此类推。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

表文件的物理位置为:$PGDATA/BASE/DATABASE_OID/PG_CLASS.RELFILENODE文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

-- 查看数据库 test 的 OID文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

#select oid,datname from pg_database where datname='test';文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

PostgreSQL是如何存储数据的?存储结构浅析文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

PostgreSQL是如何存储数据的?存储结构浅析文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

-- 查看表 t1 的 filenode文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

#select pg_relation_filepath('t1');文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

PostgreSQL是如何存储数据的?存储结构浅析PostgreSQL是如何存储数据的?存储结构浅析文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

PostgreSQL是如何存储数据的?存储结构浅析文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

 文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

- 数据文件结构 -

在 PG 中,磁盘存储和内存中的最小管理单位都是块,保存在磁盘中的数据块称为 Page,内存中的数据块称为 Buffer,表和索引称为 Relation,行称为 Tuple。数据的读写是以 Page 为最小单位,每个 Page 默认大小为 8kB,在源码编译时可通过./configure --with-blocksize=BLOCKSIZE 设置其他大小,此后都不可更改。每个表文件由多个 BLCKSZ 字节大小的 Page 组成,每个 Page 包含若干 Tuple。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

内存中的共享缓冲池缓存了 block 块(默认 1000 个),若缓冲池中的 block 块为脏,需要刷回磁盘,缓冲池细节在此不做赘述,需要时可另起一文解析。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

Page 结构

PostgreSQL是如何存储数据的?存储结构浅析文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

 文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

Page 结构包括五部分:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

PageHeaderData --在 page 头部,24 个字节长度,记录 page 的元数据信息。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

pg_lsn,存储 page 最新更改时,WAL 日志的 lsn 信息。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

pg_checksum,存储 page 的校验值。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

pd_flags,标志位文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

pg_lower,到空闲空间开头的偏移量。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

pg_upper,到空闲空间结尾的偏移量。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

pd_pagesize_version,页面大小和布局版本号信息文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

pd_prune_xid,页面上最早未删除 XMAX,如果没有则为 0。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

ItemIdData --在 page header 之后,一个记录(偏移量,长度)对的数组,指向实际 tuple 项,每个 4 字节。PostgreSQL是如何存储数据的?存储结构浅析文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

PostgreSQL是如何存储数据的?存储结构浅析文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

Free space --未分配的空间(空闲空间)。新项指针从这个区域的开头开始分配,新项从其结尾开始分配。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

Items --用来存放行数据 Tuple。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

Special space--索引访问模式相关的数据。不同的索引访问方式存放不同的数据。在普通表中为空。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

Tuple

页中的元组可细分为 “普通数据元组和 TOAST 元组”。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

TOAST (The Oversized-Attribute Storage Technique,超大属性存储技术) 主要用于存储变长数据,当待插入元组的数据大小大于约为 2KB (即页的 1/4) 时候,会自动启动 TOAST 技术来存储该元组。TOAST 较普通元组稍加复杂些,这里主要针对普通元组文件进行说明。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

PostgreSQL是如何存储数据的?存储结构浅析文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

元组内部可以分为三部分,分别是:堆元组头部(23字节)NULL值位图用户存储的数据文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

PostgreSQL是如何存储数据的?存储结构浅析文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

Pageinspect 扩展

PostgreSQL 在源码目录 contrib 下提供了许多扩展的功能,pageinspect 扩展模块提供的函数让你从低层次观察数据库页面的内容,这对于调试目的很有用。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

安装

#cd $PGSRC/contrib/pageinspect文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

#make文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

#sudo make install文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

简单使用

#psql -d test文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

test=#create extension pageinspect; -- 首次使用需创建 Extension文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

-- 创建测试表文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

drop table if exists t1;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

create table t1 (id int, name varchar(20));文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

insert into t1 values(1,'aaa');文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

-- 查看 page header&item文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

SELECT * FROM page_header(get_raw_page('t1', 0));文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

PostgreSQL是如何存储数据的?存储结构浅析文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

select * from heap_page_items(get_raw_page('t1',0));文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

PostgreSQL是如何存储数据的?存储结构浅析文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

-- 更新一行数据文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

update t1 set name='bbb' where id=1;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

PostgreSQL是如何存储数据的?存储结构浅析文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

查看 heap_page_items(),发现多了一条 item,原因是 PG 更新数据时并不修改原 tuple,而是插入一条新的 tuple,并标记原 tuple.t_xmax= 新 tuple 的事务 id。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/sjk/24527.html

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/sjk/24527.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定