ITPub博客

首页 > 数据库 > 数据库开发技术 > PG中一个表的3~8个文件是怎么来的?

PG中一个表的3~8个文件是怎么来的?

原创 数据库开发技术 作者:数据库杂记 时间:2023-02-23 07:01:00 0 删除 编辑

在PG数据库创建一张表,对应它的物理文件可以达到3~8个。很多初学者可能不太注意。认识到这种物理对应关系,在实际的使用过程中,还是十分有意义的。

我们先不急着总结,先看下边的实验:


我们先创建一个函数,用于生成随机性比较强的字符串。

CREATE OR REPLACE FUNCTION random_string( int ) RETURNS TEXT as $$
SELECT string_agg(substring('abcdefghijklmnopqrstuvwxyz', round(random() * 25 + 0.5)::integer, 1), '') FROM generate_series(1, $1); 
$$ language sql;

接着,创建目标表,为了便于集中观察,我们试图将表和其它对象都放到一个特定的表空间里。建表如下:

1mydb=# create table t(id int primary key, col2 varchar(4000)) tablespace myts;
2CREATE TABLE
3
4mydb=# insert into t select n, random_string(2800) from generate_series(1, 100) as n;
5INSERT 0 100

这时,看看相关文件:

1[22:07:31-postgres@centos2:/pgccc/myts/PG_14_202107181/21371]$ ls
237796  37799  37799_fsm  37800
3mydb=# select pg_relation_filepath('t'), pg_relation_filepath('t_pkey');
4            pg_relation_filepath             | pg_relation_filepath
5---------------------------------------------+----------------------
6 pg_tblspc/29575/PG_14_202107181/21371/37796 |
 base/21371/37801
7(1 row)
1mydb=# select oid, relname from pg_class where oid in (37796, 37799, 37800, 37801);
2  oid  |       relname
3-------+----------------------
4 37799 |
 pg_toast_37796
5 37800 | pg_toast_37796_index
6 37796 |
 t
7 37801 | t_pkey
8(4 rows)
9

这样一看,似乎t_pkey:37801文件不在myts上边。两种方式纠正:

  1.   建表时直接指下index_parameters.


 1index_parameters in UNIQUE, PRIMARY KEY, and EXCLUDE constraints are:
2
3[ INCLUDE ( column_name [, ... ] ) ]
4[ WITH ( storage_parameter [= value] [, ... ] ) ]
5[ USING INDEX TABLESPACE tablespace_name ]
6
7PRIMARY KEY index_parameters
8
9或者
10UNIQUE ( column_name [, ... ] ) index_parameters |
11  PRIMARY KEY ( column_name [, ... ] ) index_parameters |
12  EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters

重新建表如下:

1mydb=# create table t(id int primary key using index tablespace myts, col2 varchar(4000)) tablespace myts;
2CREATE TABLE
3mydb=# insert into t select n, random_string(2800) from generate_series(1, 100) as n;
4INSERT 0 100
 1[22:10:47-postgres@centos2:/pgccc/myts/PG_14_202107181/21371]$ ls
237904  37907  37907_fsm  37908  37909
3
4select oid, relname from pg_class where oid in (37904, 37907, 37908, 37909);
5  oid  |       relname
6-------+----------------------
7 37907 |
 pg_toast_37904
8 37908 | pg_toast_37904_index
9 37904 |
 t
10 37909 | t_pkey
11(4 rows)
12

看看上边的结果, toast相关的有三个文件。index有一个文件。t表有一个。

好,接着,我们对t表再执行一个vacuum:

 1mydb=# vacuum t;
2VACUUM
3[22:21:00-postgres@centos2:/pgccc/myts/PG_14_202107181/21371]$ ls -li
4total 400
534506811 -rw------- 1 postgres postgres   8192 Oct 18 22:20 37904
634506822 -rw------- 1 postgres postgres  24576 Oct 18 22:22 37904_fsm
734506821 -rw------- 1 postgres postgres   8192 Oct 18 22:22 37904_vm
834506814 -rw------- 1 postgres postgres 303104 Oct 18 22:20 37907
934506820 -rw------- 1 postgres postgres  24576 Oct 18 22:20 37907_fsm
1034506823 -rw------- 1 postgres postgres   8192 Oct 18 22:22 37907_vm
1134506816 -rw------- 1 postgres postgres  16384 Oct 18 22:20 37908
1234506817 -rw------- 1 postgres postgres  16384 Oct 18 22:20 37909


看到没有,8个文件都有了。toast出现了fsm, vm,表文件也出现了fsm, vm。这就是8个文件的来历。

提示一下,上边的随机字符串函数是为了让toast表及其索引出现内容的一种方式。因为toast表是针对原表的列而言,随机性好,就可以轻易达到长度阈值。

一个表出现这么多文件,数量如果太多的话,对表的相关文件访问性能会受到很大影响。这是由文件系统的特性决定的。


在别的数据库(如Oracle)中,看到:

这是相当恐怖的,换到PG中,是不可想象的。

而最近在某群里头,看到实际生产环境中PG里居然出现了56万张表(原因之一是非常大量采用了子分区),结果可想而知。


总之,不能不受限制的在PG中创建大量的数据库表。需要综合考虑。

原文作者:数据库杂记;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2019-04-22

  • 博文量
    276
  • 访问量
    160285