结构图
存储结构
- 逻辑存储结构:数据库内部的组织和管理数据的方式
- 物理存储结构:操作系统中组织和管理数据的方式
3. 逻辑存储结构
数据库集簇是对象的集合。一个数据库集簇可以包含多个database,多个User,每个database及它里面的对象都有他们的所有者。
3.1 数据库(Database)
在PostgreSQL中,数据库本身也是一个对象,在逻辑上彼此隔离。
表空间(tablespace)
数据库在逻辑上分成多个存储单元,称为表空间。初始化后,默认创建pg_default和pg_global两个表空间。
- pg_global:用于存放系统表。
- pg_default:该表空间的物理文件存储在数据目录中的base目录中
表空间实际上是为表指定一个存储目录。
每个用户定义的表空间都在PGDATA/pg_tblspc
目录里面有一个符号链接,它指向物理的表空间目录(即CREATE TABLESPACE
命令里指定的目录)。符号连接是用表空间的 OID 命名。物理表空间目录中有一个名称取决于PostgreSQL服务器版本的子目录,如:PG_12_201909212(下划线分割中第二部分内容即软件版本号)。
dev->devdb@[local]:5432=> select pg_relation_filepath('student');
pg_relation_filepath
---------------------------------------------
pg_tblspc/16384/PG_12_201909212/16385/16429
pg_tblspc/16384/PG_12_201909212/16385/16429
格式:$PGDATA/pg_tblspc/符号链接/PG_SERVER版本号_Catalog版本号/数据库oid/对象(表或索引)oid
。Catalog版本号可以通过pg_controldata工具获取。
-
符号链接指向物理表空间目录:如这里16384,
16384 -> /ups/data/pgdata/12/pg_usr
-
默认表空间pg_default不需要通过
pg_tblspc
来访问,而是对应于PGDATA/base
-
pg_global
表空间也不通过pg_tblspc
访问,而是对应于PGDATA/global
-
pg_relation_filepath()
函数返回任务关系的相对路径($PGDATA
)-
但是该函数只给出关系的主分支的第一个段的名称,需要追加一个段号和/或
_fsm
、_vm
或者_init
来找到与该关系相关的所有文件。
-
-
临时文件存储到在
PGDATA/base/pgsql_tmp
中,如果临时文件被指定在一个非pg_default
表空间中则它们会被创建在该表空间的pgsql_tmp
子目录中。临时文件的名称的形式为pgsql_tmpPPP.NNN
,其中PPP
是其所属后端的PID,而NNN
用于区别该后端的不同临时文件。
创建表空间
-- 创建表空间
CREATE TABLESPACE tablespace_name [ OWNER user_name ] LOCATION 'directory'
查看表空间
db
3.2 模式(schema)
模式是数据库实例的逻辑分割。数据库是被模式(schema)来切分的,一个数据库至少有一个模式,所有数据库内部的对象(object)是被创建于模式下。默认情况下,PostgreSQL自动创建public模式。Schema是数据库中的命名空间,在数据库中创建的所有对象都是在Schema中创建,一个用户可以从同一个客户端连接中访问不同的Schema。
查看当前数据库所有模式名称
select catalog_name, schema_name, schema_owner from information_schema.schemata;
SELECT nspname FROM pg_namespace;
-- 元命令查看排除information_schema和^pg_开始的内部模式名称
dn
模式的使用
创建模式
-- 1. 语法
CREATE SCHEMA schema_name [ AUTHORIZATION role_specification ] [ schema_element [ ... ] ]
CREATE SCHEMA AUTHORIZATION role_specification [ schema_element [ ... ] ]
CREATE SCHEMA IF NOT EXISTS schema_name [ AUTHORIZATION role_specification ]
CREATE SCHEMA IF NOT EXISTS AUTHORIZATION role_specification
where role_specification can be:
user_name
| CURRENT_USER
| SESSION_USER
-- 2. 为用户dev创建同名模式
CREATE SCHEMA IF NOT EXISTS AUTHORIZATION dev;
修改
ALTER SCHEMA name RENAME TO new_name
ALTER SCHEMA name OWNER TO { new_owner | CURRENT_USER | SESSION_USER }
公共模式
创建一个新数据库时,默认自动创建一个名为'public'的模式。当登录数据库时,没有指定,都是以该模式(public)操作数据库对象。
模式搜索路径
在使用一个数据库对象时,可以使用schema_name.object_name(全称)来定位对象。这会显得非常繁琐。因此,PG提供模式搜索路径解决。
show search_path;
select current_schemas(true);
-- 设置搜索路径
set search_path = "$user", public;
模式的权限
默认情况下,每个用户都可以在public模式上CREATE和USAGE权限
-- 回收public模式创建对象权限
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
-- 第一个public是模式名称,第二个PUBLIC是所有用户。
-- 授权
grant usage on schema public to public;
grant create on schema public to public;
一个数据库并不直接存储表结构等对象的,而是在数据库中逻辑创建了至少一个模式,在模式中创建了表等对象,将不同的模式指派给不同的角色,可以实现权限分离,又可以通过授权,实现模式间对象的共享,并且,还有一个特点就是:public模式可以存储大家都需要访问的对象。
段(segment)
一个段是分配给一个逻辑结构(一个表、一个索引或其他对象)的一组区,是数据库对象使用的空间的集合;段可以有表段、索引段、回滚段、临时段和高速缓存段等。
区(extent)
区是数据库存储空间分配的一个逻辑单位,它由连续数据块所组成。第一个段是由一个或多个盘区组成。当一段中间所有空间已完全使用,PostgreSQL为该段分配一个新的范围。
块(block[Page])
数据块是PostgreSQL 管理数据文件中存储空间的单位,为数据库使用的I/O的最小单位,是最小的逻辑部件。默认值8K。
3.3 表(Relation)
3.3.1 表的存储属性
TOAST
超尺寸属性存储技术-The Oversized-Attribute Storage Technique(TOAST)
PostgreSQL使用固定的页面尺寸(通常是8kB),并且不允许元组跨越多个数据页面。因此不可能直接存储非常大的字段值。为了克服这个限制,大的字段值会被压缩或分解成多个物理行存储到一张系统表中(TOAST表)。这些处理对用户都是透明的,只是在大部分的后端代码上有一些小的影响。这个技术称之为TOAST。TOAST 机制也被用来提升内存中大字段数据值的处理。
只有可变长数据类型需要TOAST支持。通常在存储的值中,前四个字节表示值的总长度(包括长度本身,以字节计)。TOAST占用使用变长类型的长度字的最高两个二进制位
填充因子(fillfactor)
fillfactor取值范围[10~100],表示插入数据时,在一个数据库中填充空间的百分比,另一部分空间预留更新时使用。
临时表
临时表生命周期结束后便会消失。
分类
- 会话级临时表:数据可以保存再整个会话的生命周期中
- 事务级临时表:数据值存在该事务的生命周期内
3.3.2 约束
- 检查约束
- 非空约束
- 唯一约束
- 主键
- 外键
3.3.3 修改表
- 添加字段
- 删除字段
- 添加约束
- 删除约束
- 修改默认值
- 修改字段数据类型
- 重命名字段
- 重命名表
3.3.4 表继承和分区表
表中的系统字段
每个表中有几个隐藏的系统字段,这些系统字段代表特殊意义。
- oid:行对象标识符
- tableoid:包含本行的表的oid。(ps_class.oid=tableoid关联查询)
- xmin:插入该行本本的事务ID
- xmax:删除此行时的事务ID
- cmin:事务内部插入类操作的命令ID
- cmax:事务内部删除类操作的命令ID
- ctid:行版本在其表内的物理位置。
OID
在内部使用对象标识符(oid)作为各种系统表的主键。
CTID
ctid表示数据行在它所处的表内的物理位置。vacuum full执行后,数据行在块内的物理位置会移动。