Ein Tablespace in PostgreSQL ist ein benannter Verweis auf ein Verzeichnis im Dateisystem. Damit kannst du steuern, wo Tabellen, Indexe oder ganze Datenbanken physisch liegen. In der Praxis kommt das Feature seltener zum Einsatz, als man denkt — der Server-Page-Cache und moderne SSDs machen viele klassische Use-Cases obsolet. Hier eine ehrliche Bestandsaufnahme: wann lohnt sich’s, wann nicht.
Was Postgres bei der Installation mitbringt
Jeder Postgres-Cluster hat von Haus aus zwei Tablespaces:
| Name | Zweck |
|---|---|
pg_default | Default-Speicher für alle Objekte ohne explizite Tablespace-Angabe. Liegt unter <PGDATA>/base/. |
pg_global | Cluster-weite Objekte (Rollen, Datenbanken-Liste, …). Liegt unter <PGDATA>/global/. |
Ohne weiteres Zutun landet alles in pg_default.
Eigenen Tablespace anlegen
CREATE TABLESPACE fast_ssd
OWNER app_owner
LOCATION '/mnt/nvme/postgres';Voraussetzungen:
- Das Verzeichnis muss vor dem Befehl existieren.
- Es muss dem Postgres-OS-User gehören (
chown postgres:postgres). - Es muss leer sein.
- Postgres muss als Superuser arbeiten —
CREATE TABLESPACEist Superuser-only.
Objekte in einem Tablespace ablegen
Beim Erstellen explizit angeben:
CREATE TABLE big_log (
id bigserial primary key,
data jsonb
) TABLESPACE fast_ssd;
CREATE INDEX big_log_data_idx ON big_log USING gin (data) TABLESPACE fast_ssd;Bestehende Tabellen umziehen:
ALTER TABLE big_log SET TABLESPACE fast_ssd;
ALTER INDEX big_log_data_idx SET TABLESPACE fast_ssd;ALTER TABLE … SET TABLESPACE kopiert die Daten physisch und nimmt einen ACCESS EXCLUSIVE-Lock auf die Tabelle — bei großen Tabellen kann das lange dauern und die Anwendung blockieren. Nicht in Stoßzeiten machen.
Default-Tablespace pro Datenbank festlegen:
ALTER DATABASE myapp SET TABLESPACE fast_ssd;Wann lohnen sich Tablespaces?
Klassische Use Cases:
- Heiße vs. kalte Daten trennen. Aktuelle Logs auf NVMe-SSD, Archiv-Daten auf langsameren HDDs.
- Indexe auf separate Disks. Reduziert I/O-Konkurrenz zwischen Heap-Reads und Index-Reads.
- Speichergrenzen pro Datenträger umgehen. Wenn ein Volume voll ist, einen weiteren mounten und neue Tabellen darauf legen.
- Performance-Isolation pro Tenant. In Multi-Tenant-Setups einen Tenant auf eine eigene Disk legen.
Aber: vieles davon ist heute weniger relevant als früher. Moderne SSDs sind so schnell, dass die I/O-Konkurrenz, die in den 2000ern durch separate Disks aufgelöst wurde, heute oft kein Problem mehr ist. Wer kann, lässt erst mal alles in pg_default und tunt erst, wenn ein konkreter Engpass nachweisbar ist.
temp_tablespaces
Für temporäre Objekte (Sort-Spill, Hash-Spill bei großen Joins, temporäre Tabellen) gibt es einen Sonderparameter:
temp_tablespaces = 'temp_fast'Sinn: ein eigenes Volume für I/O-intensive temporäre Operationen. Auf einer SSD-only-Installation lohnt sich das selten; auf gemischten Setups kann es größere ORDER BYs deutlich beschleunigen, wenn der Sort nicht in den work_mem passt.
Tablespace droppen
DROP TABLESPACE fast_ssd;Postgres lehnt ab, solange der Tablespace noch Objekte enthält. Erst alle Tabellen / Indexe in einen anderen Tablespace verschieben oder droppen, dann löst sich DROP TABLESPACE.
Inspektion
myapp=# \db+
List of tablespaces
Name | Owner | Location | Access privileges | Size
------------+----------+-----------------+-------------------+-------
pg_default | postgres | | | 128 MB
pg_global | postgres | | | 612 KB
fast_ssd | postgres | /mnt/nvme/pg | | 0 Bpg_default und pg_global haben keinen LOCATION — sie liegen innerhalb des PGDATA-Verzeichnisses.
Zu welchem Tablespace gehört eine Tabelle?
SELECT c.relname,
COALESCE(t.spcname, 'pg_default') AS tablespace
FROM pg_class c
LEFT JOIN pg_tablespace t ON t.oid = c.reltablespace
WHERE c.relkind = 'r' AND c.relname = 'big_log';Wenn reltablespace = 0, gehört die Tabelle zum Default-Tablespace der Datenbank.
FAQ
Geht das auch in der Cloud (RDS, Cloud SQL, …)?
In den meisten Managed-Postgres-Diensten nein. Du hast keinen Filesystem-Zugriff, keinen Superuser, und der Anbieter verwaltet Storage selbst. AWS RDS bietet seit Kurzem zwar rds_tablespace für eingeschränkte Anwendungsfälle, aber der typische Cloud-Setup ist „nicht änderbar”. Wer Tablespaces wirklich braucht, muss selbst betreiben.
Sind Tablespaces clustergebunden?
Ja. Ein Tablespace gehört zu einem Cluster, nicht zu einer Datenbank. Wenn du pg_basebackup/Streaming Replication aufsetzt, repliziert die Replika auch die Tablespace-Pfade — die Verzeichnisse müssen auf dem Replica-Host am selben Ort existieren (oder per --tablespace-mapping umgemappt werden).
Was passiert beim Backup mit Tablespaces?
pg_dump ist davon unabhängig — es macht logische Backups und ignoriert physische Speicherorte. pg_basebackup hingegen kopiert das gesamte Cluster inkl. aller Tablespace-Verzeichnisse und braucht ggf. --tablespace-mapping=…, wenn die Pfade auf dem Restore-Host anders sein sollen.
Kann ein Tablespace ueber mehrere Cluster geteilt werden?
Nein. Auch wenn das Verzeichnis theoretisch von zwei Postgres-Instanzen gleichzeitig erreichbar wäre, wäre das Datenchaos. Ein Tablespace gehört zu einem Cluster, exklusiv.
Wie schwer ist die Migration zwischen Tablespaces?
ALTER TABLE … SET TABLESPACE ist eine physische Datenkopie mit ACCESS EXCLUSIVE-Lock — die Tabelle ist während der gesamten Operation blockiert. Bei großen Tabellen ist das ein Wartungsfenster-Job. Alternativ: Logical Replication mit Cutover, falls Downtime nicht tolerierbar ist.
Wann sollte ich Tablespaces ueberhaupt anfangen einzusetzen?
Erst wenn ein konkretes Problem nachweisbar ist — z. B. dass das Volume voll wird oder I/O-Profile pro Tabelle stark abweichen. Auf SSD-only-Installationen ist das eher selten. Vorher: pg_default reicht.
Weiterführende Ressourcen
Externe Quellen
- Tablespaces – PostgreSQL Documentation
- CREATE TABLESPACE – PostgreSQL Documentation
- ALTER TABLE … SET TABLESPACE
- pg_basebackup —tablespace-mapping
- temp_tablespaces – Run-time Configuration