Tablespaces

Initially there are two tablespaces in the cluster. We can query them from the system catalog:

α=> SELECT spcname FROM pg_tablespace;
  spcname   
------------
 pg_default
 pg_global
(2 rows)

Obviously pg_tablespace is one of the cluster-level tables.


Similar information is shown by the psql command:

α=> \db
       List of tablespaces
    Name    |  Owner   | Location 
------------+----------+----------
 pg_default | postgres | 
 pg_global  | postgres | 
(2 rows)


To create a new tablespace you need to create an empty directory first. The directory must be owned by the user which runs PostgreSQL server (usually postgres):

postgres$ mkdir /var/lib/postgresql/ts_dir

Now we can create a tablespace by specifying its directory:

α=> CREATE TABLESPACE ts LOCATION '/var/lib/postgresql/ts_dir';
CREATE TABLESPACE

α=> \db
                List of tablespaces
    Name    |  Owner   |          Location          
------------+----------+----------------------------
 pg_default | postgres | 
 pg_global  | postgres | 
 ts         | student  | /var/lib/postgresql/ts_dir
(3 rows)


When creating a database, a default tablespace can be specified for it:

α=> CREATE DATABASE test TABLESPACE ts;
CREATE DATABASE
α=> \c test
You are now connected to database "test" as user "student".

This means that by default (when not explicitly specified otherwise) every object will be created in that tablespace.

α=> CREATE TABLE t(s text);
CREATE TABLE
α=> INSERT INTO t SELECT g.id::text FROM generate_series(1,100000) g(id);
INSERT 0 100000
α=> CREATE INDEX ON t(s);
CREATE INDEX
α=> VACUUM t;
VACUUM

We can get the location of an object's files this way:

α=> SELECT pg_relation_filepath('t');
            pg_relation_filepath             
---------------------------------------------
 pg_tblspc/17568/PG_11_201809051/17569/17570
(1 row)


Let's look at the files:

postgres$ ls -l /var/lib/postgresql/11/alpha/pg_tblspc/17568/PG_11_201809051/17569/17570*
-rw------- 1 postgres postgres 3620864 фев 27 15:37 /var/lib/postgresql/11/alpha/pg_tblspc/17568/PG_11_201809051/17569/17570
-rw------- 1 postgres postgres   24576 фев 27 15:37 /var/lib/postgresql/11/alpha/pg_tblspc/17568/PG_11_201809051/17569/17570_fsm
-rw------- 1 postgres postgres    8192 фев 27 15:37 /var/lib/postgresql/11/alpha/pg_tblspc/17568/PG_11_201809051/17569/17570_vm

We can see that the files belong to the different forks: main, vm, and fsm.


Objects can be moved between tablespaces, although it requires physical copying of the data to other files (unlike moving between schemas):

α=> ALTER TABLE t SET TABLESPACE pg_default;
ALTER TABLE
α=> SELECT pg_relation_filepath('t');
 pg_relation_filepath 
----------------------
 base/17569/17577
(1 row)


Objects sizes

We can get the size of a database and its objects by the means of several functions.

α=> SELECT pg_database_size('test');
 pg_database_size 
------------------
         13461779
(1 row)

We can format the numbers in a human-readable form:

α=> SELECT pg_size_pretty(pg_database_size('test'));
 pg_size_pretty 
----------------
 13 MB
(1 row)


Total size of a table, including its indexes:

α=> SELECT pg_size_pretty(pg_total_relation_size('t'));
 pg_size_pretty 
----------------
 5776 kB
(1 row)


Table size without indexes...

α=> SELECT pg_size_pretty(pg_table_size('t'));
 pg_size_pretty 
----------------
 3576 kB
(1 row)

...and indexes alone:

α=> SELECT pg_size_pretty(pg_indexes_size('t'));
 pg_size_pretty 
----------------
 2200 kB
(1 row)


Also we can get separate forks sizes, for example:

α=> SELECT pg_size_pretty(pg_relation_size('t','vm'));
 pg_size_pretty 
----------------
 8192 bytes
(1 row)


And one more function for a tablespace size:

α=> SELECT pg_size_pretty(pg_tablespace_size('ts'));
 pg_size_pretty 
----------------
 9582 kB
(1 row)


Now let's drop the database.

α=> \c postgres
You are now connected to database "postgres" as user "student".
α=> DROP DATABASE test;
DROP DATABASE

We can drop the tablespace as well, as long there are no objects in it:

α=> DROP TABLESPACE ts;
DROP TABLESPACE

The end of demonstration.