PostgreSQL表空间以及表空间与数据库的文件存储
PostgreSQL表空间VS数据库表空间:PostgreSQL中,表空间是一个逻辑概念,安装好PostgreSQL后有自带的默认的表空间,也可以创建用户表空间,每个表空间,又对应着一个物理上的路径。
数据库:PostgreSQL数据库也是一个逻辑概念,数据库强绑定到一个表空间,但是数据库中的对象(表,索引等)可以指定到不同的表空间中,这个有点灵活,照旧凌乱?
表空间与数据库:一个表空间可以包含多个数据库,数据库中的不同的表,也可以分布于不同的表空间中,两者没有包含和被包含的关系。是不是已经凌乱了。。。。。。
https://img2024.cnblogs.com/blog/380271/202504/380271-20250424162201545-6693033.png
PostgreSQL默认pg_default和pg_global表空间
默认情况下,PostgreSQL有两个表空间,pg_default和pg_global,如下查看表空间信息
-- PostgreSQL表空间查询
SELECT
spcname,
pg_get_userbyid(spcowner) AS spc_owner,
pg_tablespace_location(oid) AS location
FROM pg_tablespace
ORDER BY spcname;
spcname |spc_owner|location |
----------+---------+--------------------------------+
pg_default|postgres | |
pg_global |postgres | |pg_default:数据库级系统表,临时表对象,对应的路径为pg_instance/data/base。如果存在用户自界说数据库,每个自界说数据库位于pg_instance/data/base路径下,每个数据库一个文件夹
pg_global:集群级共享系统表,对应的路径为pg_instance/data/global
在默认表空间上创建自界说数据库
当创建数据库的时候,如果没有指定表空间,那么数据库会创建在default表空间。对于数据库的物理文件位置:如果存在用户自界说数据库,每个自界说数据库位于pg_instance/data/base路径下,每个数据库一个文件夹
--默认情况下数据会创建在默认(pg_default)表空间
create database db01;
--查看数据库与对应的表空间以及物理位置
SELECT
d.datname AS database,
t.spcname AS table_space,
CASE
WHEN t.spcname = 'pg_default' THEN
current_setting('data_directory') || '/base/' || d.oid
WHEN t.spcname = 'pg_global' THEN
current_setting('data_directory') || '/global'
ELSE
pg_tablespace_location(t.oid)
END AS pyhsical_location
FROM pg_database d
JOIN pg_tablespace t ON d.dattablespace = t.oid
ORDER BY d.datname;
database |table_space|pyhsical_location |
---------+-----------+-----------------------------------------+
db01 |pg_default |/usr/local/pgsql16/pg9000/data/base/16400|
postgres |pg_default |/usr/local/pgsql16/pg9000/data/base/5 |
template0|pg_default |/usr/local/pgsql16/pg9000/data/base/4 |
template1|pg_default |/usr/local/pgsql16/pg9000/data/base/1 | PostgreSQL默认数据文件目录的物理存储结构如下
https://img2024.cnblogs.com/blog/380271/202504/380271-20250424143400313-191775330.png
目录的表明如下
PGDATA/
├── base/ # 核心数据库文件存储目录
├── global/ # 集群范围(跨数据库)的系统表
├── pg_tblspc/ # 自定义表空间的符号链接
│ └── 12345 -> /mnt/ssd # 指向自定义表空间物理位置的链接
├── pg_wal/ # WAL(预写日志)文件
├── pg_xact/ # 事务提交状态数据(旧版本为pg_clog)
├── pg_subtrans/ # 子事务状态数据
├── pg_multixact/ # 多事务状态信息
├── pg_commit_ts/ # 事务提交时间戳
├── pg_replslot/ # 复制槽数据
├── pg_snapshots/ # 导出的事务快照
├── pg_stat/ # 统计信息的永久存储
├── pg_stat_tmp/ # 统计信息的临时存储
├── pg_logical/ # 逻辑解码数据
│ ├── snapshots/ # 逻辑解码快照
│ └── mappings/ # 复制标识映射
├── postgresql.conf # 主配置文件
├── pg_hba.conf # 客户端认证配置文件
├── pg_ident.conf # 用户名映射文件
├── postmaster.opts # 上次启动服务器的命令行选项
└── postmaster.pid # 当前运行的postmaster进程ID
PostgreSQL用户自界说表空间
首选必要在Linux上创建一个表空间的路径,并授权给postgres用户
linux:
root@iZ7xv55xixens4mlf4jusqZ:# mkdir /usr/local/pgsql16/pg9000/db_tbs
root@iZ7xv55xixens4mlf4jusqZ:# chown postgres:postgres/usr/local/pgsql16/pg9000/db_tbs然后再数据库中创建表空间,目的是做一个物理文件和逻辑文件的映射
psql:
CREATE TABLESPACE db_tbs LOCATION '/usr/local/pgsql16/pg9000/db_tbs';创建表空间之后,会在PostgreSQL实例的data目录下创建一个软毗连,指向上述表空间的物理地址
root@iZ7xv55xixens4mlf4jusqZ:/usr/local/pgsql16/pg9000/data# cd pg_tblspc
root@iZ7xv55xixens4mlf4jusqZ:/usr/local/pgsql16/pg9000/data/pg_tblspc# ll
total 8
drwx------2 postgres postgres 4096 Apr 24 10:37 ./
drwx------ 19 postgres postgres 4096 Apr 24 00:00 ../
lrwxrwxrwx1 postgres postgres 32 Apr 24 10:37 24603 -> /usr/local/pgsql16/pg9000/db_tbs/再次查看表空间,发现多了一个上面的表空间
--查看表空间以及其路径信息
SELECT
spcname,
pg_get_userbyid(spcowner) AS spc_owner,
pg_tablespace_location(oid) AS location
FROM pg_tablespace
ORDER BY spcname;
spcname |spcowner|usr |
----------+--------+--------------------------------+
db_tbs |postgres|/usr/local/pgsql16/pg9000/db_tbs|
pg_default|postgres| |
pg_global |postgres| |
PostgreSQL中使用自界说表空间创建数据库
创建用户自界说数据库,指定到自界说的表空间中
--创建数据库指定表空间
create database test_db01 tablespace db_tbs;
-- 查看数据库与对应的表空间
SELECT
d.datname,
t.spcname ,
pg_size_pretty(pg_database_size(d.datname)) AS "DBSize"
FROM pg_database d
JOIN pg_tablespace t ON d.dattablespace = t.oid
ORDER BY d.datname;
datname|spcname |DBSize |
---------+----------+-------+
db01 |pg_default|8604 kB|
postgres |pg_default|7324 kB|
template0|pg_default|7252 kB|
template1|pg_default|7161 kB|
test_db01|db_tbs |7372 kB| ----这个是自定义数据库的与对应的表空间
PostgreSQL中:库,表,索引,对应表空间之间的关系
--当前数据库下:创建表时不指定表空间,默认位于数据库的表空间下
CREATE TABLE table01 (
c1 integer NOT NULL,
c2 varchar(20),
c3 timestamp
);
--当前数据库下:创建表时显式指定表空间,表空间为当前数据库的表空间
CREATE TABLE table02 (
c1 integer NOT NULL,
c2 varchar(20),
c3 timestamp
) TABLESPACE db_tbs;
--当前数据库下:创建表时显式指定表空间,表空间为非数据库的表空间
CREATE TABLE table03 (
c1 integer NOT NULL,
c2 varchar(20),
c3 timestamp
) TABLESPACE pg_default;
-- 创建索引,如果不指定表空间,默认为数据库的表空间
CREATE INDEX idx_tb1_1 ON table01 (c1);
-- 创建索引,可以指定为数据库的表空间
CREATE INDEX idx_tb1_2 ON table01 (c2) tablespace db_tbs;
-- 创建索引,可以指定为数据库的其他的表空间
CREATE INDEX idx_tb1_3 ON table01 (c3) tablespace pg_default;数据库,表,索引与表空间之间的关系,可以参考如下这个图,能表明他们之间的关系:
1,表空间对应一个物理路径
2,一个数据库可以完全归属于一个表空间
3,一个数据库也可以跨多个表空间
https://img2024.cnblogs.com/blog/380271/202504/380271-20250424162201545-6693033.png
查看上述自界说对象,也即数据库的表对应的数据库,表空间,schema,物理文件路径,以及大小
这里遇到一个非常扯淡的问题,pg_class的reltablespace字段,
如果是系统表空间,该字段对应系统表空间的oid,如果是用户自界说表空间,该字段是0,也就是默认的归属的数据库的表空间,此时去查库的表空间
--查看数据库的表对应的数据库,表空间,schema,物理文件路径,以及大小
SELECT
db.datname as databae_name,
case
when ts.spcname is not null then ts.spcname
--这里有一个非常扯淡的问题,pg_class的reltablespace字段,
--如果是系统表空间,该字段对应系统表空间的oid,如果是用户自定义表空间,该字段是0,也就是默认的归属的数据库的表空间,此时去查库的表空间
when ts.spcname isnull then
(
SELECT
t.spcname
FROM pg_database d
JOIN pg_tablespace t ON d.dattablespace = t.oid
where d.datname = current_database()
) end as table_space,
n.nspname as schema_name,
c.relname AS object_name,
CASE c.relkind
WHEN 'r' THEN 'table'
WHEN 'i' THEN 'index'
WHEN 't' THEN 'toast_table'
ELSE c.relkind::text
END AS object_type,
pg_relation_filepath(c.oid) AS physical_location,
pg_size_pretty(pg_relation_size(c.oid)) AS object_size
FROM pg_class c
inner join pg_database db on db.datname = current_database()
LEFT JOIN pg_tablespace ts ON c.reltablespace = ts.oid
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE
n.nspname NOT in ('pg_catalog','pg_toast','information_schema') --排除系统表
AND (c.relkind = 'r' OR c.relkind = 'i' OR c.relkind = 't')
ORDER BY
n.nspname,
CASE WHEN c.relkind = 'r' THEN c.relname
ELSE
(
SELECT relname FROM pg_class WHERE oid = (SELECT indrelid FROM pg_index WHERE indexrelid = c.oid)
) END,
CASE WHEN c.relkind = 'r' THEN 0 ELSE 1 END,
c.relname;
databae_name|table_space|schema_name|object_name|object_type|physical_location |object_size|
------------+-----------+-----------+-----------+-----------+-------------------------------------------+-----------+
test_db01 |db_tbs |public |table01 |table |pg_tblspc/24603/PG_16_202307071/24604/24637|0 bytes |
test_db01 |db_tbs |public |idx_tb1_1|index |pg_tblspc/24603/PG_16_202307071/24604/24646|8192 bytes |
test_db01 |db_tbs |public |idx_tb1_2|index |pg_tblspc/24603/PG_16_202307071/24604/24647|8192 bytes |
test_db01 |pg_default |public |idx_tb1_3|index |base/24604/24648 |8192 bytes |
test_db01 |db_tbs |public |table02 |table |pg_tblspc/24603/PG_16_202307071/24604/24640|0 bytes |
test_db01 |pg_default |public |table03 |table |base/24604/24643 |0 bytes |
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]