21.6. 表空间

PostgreSQL里的表空间允许数据库管理员在文件系统里定义那些代表 数据库对象的文件存放位置。一旦创建了表空间,那么就可以在创建数据库对象的时候引用它。

通过使用表空间,管理员可以控制一个 PostgreSQL 安装的磁盘布局。 这么做至少有两个用处。首先,如果初始化集群所在的分区或者卷用光了空间, 而又不能逻辑上扩展或者别的什么操作,那么表空间可以在一个不同的分区上创建和使用, 直到系统可以重新配置。

第二,表空间允许管理员根据数据库对象的使用模式安排数据位置,从而优化性能。 比如,一个很频繁使用的索引可以放在非常快并且非常可靠的磁盘上,比如一种非常贵的固态设备。 而同时,一个存储归档的数据,很少使用的或者对性能要求不高的表可以存储在一个便宜但比较慢的磁盘系统上。

要定义一个表空间,使用 命令,比如:

CREATE TABLESPACE fastspace LOCATION '/mnt/sda1/postgresql/data';

这个位置必须是一个现有的空目录,并且属于 PostgreSQL 系统用户。 所有随后在该表空间创建的对象都将被存放在这个目录下的文件里。

Note: 当在逻辑文件系统上定义不止一个表空间时,并没有那么多的条件,因为您无法控制逻辑文件系统中的特定文件的位置。 然而,的PostgreSQL不执行任何这样的限制,并且实际上是不直接识别您的文件系统边界,它仅仅只是存储在你定义的目录中。

创建表空间时必须是数据库超级用户, 但在创建完之后之后,可以给数据库普通用户授予create的权限(在该表空间上的权限)来使用它。

表、索引和整个数据库都可以放在特定的表空间里。想要这么做的话, 在给定表空间上有 CREATE权限的用户必须把表空间的名字以一个参数的形式传递给相关的命令。 比如,下面的命令在表空间space1上创建一个表:

CREATE TABLE foo(i int) TABLESPACE space1;

另外,还可以使用default_tablespace参数:

SET default_tablespace = space1;
CREATE TABLE foo(i int);

只要default_tablespace被设置为非空字符串, 那么它就为没有明确使用 TABLESPACE 子句的CREATE TABLECREATE INDEX 命令提供一个隐含的子句。

还有temp_tablespaces参数, 决定临时表和索引的位置,以及如用于对大数据进行排序的临时文件。 这可以是一个表空间名的列表,而不是只有一个,因此,与临时对象有关的负载可以遍及 多个表空间。列表中的一个随机成员每次采摘时创建一个临时对象。

与数据库相关联的表空间用来存储该数据库的系统目录表。 此外,如果没有TABLESPACE条款给出,并且 default_tablespace或者 temp_tablespaces(如适用)没有进行其他的声明时,它还是在该数据库中创建的表,索引,临时文件的默认表空间。 如果没有创建数据库时没有声明表空间,它会使用与模板数据库相同的表空间。

当初始化数据库集群时,自动创建两个表空间: pg_global(用于存储共享系统目录表)和 pg_default表空间,这个表空间是表是默认的表空间 template1template0数据库的默认表空间,因此,如果CREATE DATABASE时没有 通过TABLESPACE字句声明表空间,那么,pg_default表空间会是作为该数据库的默认表空间。

表空间一旦被创建,那么它就可以被任何数据库使用,并提供给 发出请求的用户足够的权限。这也意味着,一个表空间 只有在表空间中所有数据库下所有对象都被删除掉之后才可以被删掉。

要删除一个空的表空间,使用 DROP TABLESPACE 命令。

通过查看pg_tablespace 系统表,可以获取已有的表空间的属性,比如

SELECT spcname FROM pg_tablespace;

psql程序的 \db 命令也可以用于列出现有表空间。

PostgreSQL通过使用符号连接来简化表空间的实施,这就意味着表空间只能在支持符号连接的系统上使用。

$PGDATA/pg_tblspc 目录下包含指向集群里定义的每个非内置表空间的符号连接。 尽管我们不建议,但是我们还是可能通过手工重定义这些连接来调整表空间的布局。 两个警告:在服务器运行时,以及重启服务器之后,更新 pg_tablespace 表的显示新位置时不能这么做。 否则pg_dump 将继续显示旧的表空间位置。