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
| Funktion | Was 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.
