Tabellen-, Index- und Datenbankgrößen in PostgreSQL ermitteln

Die Abfrage, die alle eigentlich wollen — die größten Tabellen, Indexe inbegriffen — dann die drei Größenfunktionen und was jede wirklich misst.

-- Die 20 größten Tabellen (inklusive Indexe und TOAST):
SELECT c.oid::regclass AS table_name,
       pg_size_pretty(pg_total_relation_size(c.oid)) AS total,
       pg_size_pretty(pg_table_size(c.oid))          AS table_only,
       pg_size_pretty(pg_indexes_size(c.oid))        AS indexes
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r'
  AND n.nspname NOT IN ('pg_catalog', 'information_schema')
ORDER BY pg_total_relation_size(c.oid) DESC
LIMIT 20;

Die drei Größenfunktionen, unterschieden

FunktionWas sie misst
pg_relation_size('t')Nur der Haupt-Heap — keine Indexe, kein TOAST (der ausgelagerte Speicher für große Werte).
pg_table_size('t')Die eigentliche Tabelle: Heap + TOAST + Hilfs-Maps. Immer noch keine Indexe.
pg_total_relation_size('t')Alles: Tabelle + TOAST + alle ihre Indexe. Das ist „wie viel Festplatte mich diese Tabelle kostet".

Verpacken Sie jede davon in pg_size_pretty(...) für menschenlesbare Einheiten. Eine Tabelle mit langen Text-/JSONB-Spalten kann den Großteil ihrer Bytes in TOAST haben — wenn pg_table_size pg_relation_size in den Schatten stellt, sind sie dort.

Weitere Einzeiler

-- Größe einer einzelnen Tabelle / eines Index / einer Datenbank:
SELECT pg_size_pretty(pg_total_relation_size('public.orders'));
SELECT pg_size_pretty(pg_relation_size('orders_created_at_idx'));
SELECT pg_size_pretty(pg_database_size(current_database()));

-- Alle Datenbanken des Clusters:
SELECT datname, pg_size_pretty(pg_database_size(datname))
FROM pg_database
ORDER BY pg_database_size(datname) DESC;

-- Die größten Indexe:
SELECT c.oid::regclass AS index_name,
       pg_size_pretty(pg_relation_size(c.oid)) AS size
FROM pg_class c
WHERE c.relkind = 'i'
ORDER BY pg_relation_size(c.oid) DESC
LIMIT 20;

Größe auf der Festplatte ≠ Live-Daten

Diese Funktionen messen den allokierten Festplattenplatz, was Bloat einschließt: Platz, der von toten Zeilenversionen belegt wird, die Vacuum nicht zurückgewonnen hat (und den einfaches Vacuum der Tabelle zurückgibt, nicht dem Betriebssystem). Eine 50-GB-Tabelle enthält vielleicht 20 GB Live-Zeilen. Wenn eine Tabelle für ihre Zeilenzahl viel zu groß aussieht, ist das eine Bloat-Untersuchung, kein Speicher-Upgrade.

Partitionierte Tabellen: die Elterntabelle selbst ist leer — summieren Sie die Partitionen, z. B. per Join mit pg_inherits, oder überschlagen Sie sie mit \d+ parent_name in psql.

🔍 Tabelle verdächtig groß? Lesen Sie VACUUM, Autovacuum und Bloat. Geht die Festplatte tatsächlich zur Neige? Es gibt eine Fehlerseite für No space left on device — prüfen Sie die Replication-Slots, bevor Sie Speicher kaufen.