PHP实战中知识总结 / PgSQL - 存储结构
一、逻辑结构
如图,postgresql逻辑结构层级划分:databse cluster --> database --> schema --> table(index) --> segments --> pages --> tuples。
(1)segment:数据文件会被切割成多个segmemts, 默认1G;
(2)page(block):每个segment内部都会被划分成多个pages,默认8k,page是IO操作的最小单位;
(3)tuple:每行记录叫tuple,每个tuple对应一个tid(tuple identififiers);
(4)relation:table、index、sequence, view, function等叫relation;
(5)oid:object identififiers (OIDs),每个relation都是通过对应的oid进行管理;
(6)relfifilenode:一般情况 relfifilenode = oid,用于管理具体的数据文件;
PostgreSQL 中的所有数据库对象都由各自的对象标识符 (OID) 内部管理,它们是无符号的 4 字节整数。 根据对象的类型,数据库对象和相应 OID 之间的关系存储在适当的系统目录中。 例如,数据库和堆表的OID分别存储在pg_database和pg_class中。
// 查看database cluster,不同的db之间的数据是不能访问的
postgres=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
postgres | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 |
template0 | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
test | postgres | UTF8 | zh_CN.UTF-8 | zh_CN.UTF-8 |
(4 rows)
// 查看schemas,同一个db下的不同schema的数据是可以访问的
postgres=# \dn
List of schemas
Name | Owner
----------+----------
myschema | postgres
public | postgres
(2 rows)
postgres=# \d
List of relations
Schema | Name | Type | Owner
--------+--------------------+----------+----------
public | alerts | table | postgres
public | alerts_id_seq | sequence | postgres
public | goods | table | postgres
public | pg_stat_statements | view | postgres
public | products | table | postgres
public | test | table | postgres
(6 rows)
// 每个tuple都有一个tid,表示第0个page的第1行
postgres=\# select ctid, name, age from t001;
ctid | name | age
-------+-----------+-----
(0,1) | damon0668 | 1
(0,2) | damon0669 | 2
// 查看database的oid
postgres=# select oid, datname from pg_database where datname = 'test';
oid | datname
-------+---------
16411 | test
(1 row)
// 查看table的oid和relfilenode,一般情况 oid = relfilenode
postgres=# select oid, relfilenode, relname from pg_class where relname = 'test';
oid | relfilenode | relname
-------+-------------+---------
16384 | 16550 | test
(1 row)
// truncate之后,oid不变,relfilenode变了,此时oid != relfilenode
postgres=# TRUNCATE test;
TRUNCATE TABLE
postgres=# select oid, relfilenode, relname from pg_class where relname = 'test';
oid | relfilenode | relname
-------+-------------+---------
16384 | 16720 | test
(1 row)
二、物理结构
[root@izwz91quxhnlkan8kjak5hz postgres]# tree -L 2
.
├── base
│ ├── 1 // 数据库oid
│ │ ├── 112 // 数据文件,对应表的relfilenode
│ │ ├── 113
│ │ ├── 113.1 // 被截取的数据文件段
│ │ ├── 1247
│ │ ├── 1247_fsm // free space map,记录每一个page的空闲空间
│ │ ├── 1247_vm // 可见性映射表,显示占用的tuple,扫描的时候会跳过这些tuple
│ ├── 13579
│ ├── 13580
│ ├── 16411
│ └── pgsql_tmp // 临时文件存储目录
├── global
│ ├── 1213
│ ├── 1213_fsm
│ ├── 1213_vm
│ ├── 1214
│ ├── 1214_fsm
│ ├── 1214_vm
│ ├── 1232
│ ├── pg_control // 用于存储全局控制信息
│ ├── pg_filenode.map // pg_class里relfilenode为0的系统表,OID与文件的硬编码映射
│ └── pg_internal.init // 系统表的cache文件,用于加快读取。默认不存在,查询系统表后自动产生
├── pg_commit_ts // 该目录包含已提交事务的时间
├── pg_dynshmem // 该目录包含动态共享内存子系统使用的文件
├── pg_hba.conf // 客户端认证控制文件
├── pg_ident.conf // 用来配置哪些操作系统用户可以映射为哪个数据库用户
├── pg_logical // 逻辑复制的状态数据的目录
│ ├── mappings
│ ├── replorigin_checkpoint
│ └── snapshots
├── pg_multixact // 存储多事务状态数据的子目录(用户共享的行锁)
│ ├── members
│ └── offsets
├── pg_notify // 包含LISTEN/NOTIFY状态数据的目录
├── pg_replslot // 该目录包含了复制槽的数据
├── pg_serial // 已提交的可序列化事务信息的目录
├── pg_snapshots // 储存导出的快照
├── pg_stat // 统计信息的存储目录
├── pg_stat_tmp // 统计信息的存储临时目录
│ ├── db_0.stat
│ ├── db_13580.stat
│ ├── db_16411.stat
│ ├── global.stat
│ └── pgss_query_texts.stat
├── pg_subtrans // 存储子事务状态数据的目录
│ └── 0000
├── pg_tblspc // 存储表空间的符号链接
├── pg_twophase // 用于存储预备事务状态文件的目
├── PG_VERSION
├── pg_wal // 保存预写日志的目录
│ ├── 000000010000000400000050
...