22.6. Tablespaces

PostgreSQL 中的表空间允许数据库 Management 员在文件系统中定义可以存储代表数据库对象的文件的位置。创建表对象后,可以在创建数据库对象时按名称引用表空间。

通过使用表空间,Management 员可以控制 PostgreSQL 安装的磁盘布局。这至少在两个方面很有用。首先,如果初始化集群的分区或卷空间不足且无法扩展,则可以在另一个分区上创建表空间并使用该表空间,直到重新配置系统为止。

其次,表空间允许 Management 员使用数据库对象使用模式的知识来优化性能。例如,可以将使用频率很高的索引放置在非常快速,高度可用的磁盘上,例如昂贵的固态设备。同时,可以将存储很少使用或性能要求不高的存档数据的表存储在价格较低,速度较慢的磁盘系统上。

Warning

即使位于主 PostgreSQL 数据目录之外,表空间还是数据库集群的组成部分,并且不能将其视为数据文件的自主集合。它们取决于主数据目录中包含的元数据,因此不能附加到其他数据库集群或单独备份。同样,如果丢失表空间(文件删除,磁盘故障等),则数据库集群可能变得不可读或无法启动。将表空间放在 RAM 磁盘等临时文件系统上会危及整个群集的可靠性。

要定义表空间,请使用CREATE TABLESPACE命令,例如:

CREATE TABLESPACE fastspace LOCATION '/ssd1/postgresql/data';

该位置必须是 PostgreSQLos 用户拥有的现有空目录。随后在表空间中创建的所有对象将存储在此目录下的文件中。该位置不得位于可移动存储或临时存储中,因为如果表空间丢失或丢失,群集可能无法运行。

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设置为除空字符串以外的任何内容时,它将为CREATE TABLECREATE INDEX命令提供一个隐式的TABLESPACE子句,而这些命令没有显式的。

还有一个temp_tablespaces参数,该参数确定临时表和索引以及用于诸如对大型数据集进行排序之类的目的的临时文件的位置。这可以是表空间名称的列表,而不只是一个,因此与临时对象相关的负载可以分布在多个表空间上。每次要创建临时对象时,都会选择列表的随机成员。

与数据库关联的表空间用于存储该数据库的系统目录。此外,如果未提供TABLESPACE子句,并且default_tablespacetemp_tablespaces(视情况而定)未指定其他选择,则它是用于在数据库内创建的表,索引和临时文件的默认表空间。如果创建数据库时未为其指定表空间,则该数据库将使用与其复制的模板数据库相同的表空间。

初始化数据库集群时,将自动创建两个表空间。 pg_global表空间用于共享系统目录。 pg_default表空间是template1template0数据库的默认表空间(因此,也将是其他数据库的默认表空间,除非被CREATE DATABASE中的TABLESPACE子句覆盖)。

一旦创建,就可以从任何数据库中使用表空间,前提是发出请求的用户具有足够的特权。这意味着在删除使用该表空间的所有数据库中的所有对象之前,无法删除表空间。

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

要确定现有表空间的集合,请检查pg_tablespace系统目录,例如

SELECT spcname FROM pg_tablespace;

psql程序的\db元命令对于列出现有表空间也很有用。

PostgreSQL 利用符号链接来简化表空间的实现。这意味着表空间只能在支持符号链接的系统上使用。

目录$PGDATA/pg_tblspc包含指向群集中定义的每个非内置表空间的符号链接。尽管不建议这样做,但可以通过重新定义这些链接来手动调整表空间布局。在服务器运行期间,任何情况下都不要执行此操作。请注意,在 PostgreSQL 9.1 和更早版本中,您还需要使用新位置更新pg_tablespace目录。 (如果不这样做,pg_dump将 continue 输出旧表空间位置.)