Vor kurzem habe ich einen PostgreSQL 8.2.11-Server auf 8.4 aktualisieren lassen, um die Autovakuum-Funktionen zu nutzen und mit 30 anderen PGSQL-Servern in Einklang zu stehen. Dies wurde von einer separaten IT-Gruppe durchgeführt, die die Hardware verwaltet, sodass wir bei anderen Upgrades keine große Auswahl haben (9+ werden für eine Weile nicht angezeigt). Der Server befindet sich in einer sehr geschlossenen Umgebung (isoliertes Netzwerk, eingeschränkte Root-Rechte) und läuft unter RHEL5.5 (i686). Nach dem Upgrade ist die Datenbank ständig auf 5 bis 6 GB pro Tag angewachsen. Normalerweise ist die Datenbank insgesamt ~ 20 GB groß. Derzeit sind es ~ 89 GB. Wir haben ein paar andere Server, die äquivalente Datenbanken ausführen und die Datensätze über eine Drittanbieteranwendung miteinander synchronisieren (einer, auf den ich keinen Zugriff auf das Innenleben habe). Die anderen Datenbanken haben ~ 20 GB, wie sie sein sollten.
Wenn Sie das folgende SQL ausführen, ist es ziemlich offensichtlich, dass es ein Problem mit einer bestimmten Tabelle gibt, insbesondere mit der TOAST-Tabelle.
SELECT nspname || '.' || relname AS "relation",
pg_size_pretty(pg_relation_size(C.oid)) AS "size"
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE nspname NOT IN ('pg_catalog', 'information_schema')
ORDER BY pg_relation_size(C.oid) DESC
LIMIT 20;
Welches produziert:
Beziehung | Größe ------------------------------------ + --------- pg_toast.pg_toast_16874 | 89 GB paars00.warmstates | 1095 MB ... (20 Zeilen)
Diese TOAST-Tabelle ist für eine Tabelle namens "Zeitreihen" vorgesehen, in der große Datensätze von Blobbed-Daten gespeichert werden. Ein SUM(LENGTH(blob)/1024./1024.)
aller Datensätze in Zeitreihen ergibt ~ 16 GB für diese Spalte. Es sollte keinen Grund geben, warum die TOAST-Tabelle dieser Tabelle so groß sein sollte wie sie ist.
Ich habe eine durchgeführt VACUUM FULL VERBOSE ANALYZE timeseries
, und das Vakuum läuft ohne Fehler vollständig ab.
INFO: Staubsaugen "pg_toast.pg_toast_16874"
INFO: "pg_toast_16874": 22483 entfernbare, 10475318 nicht entfernbare Zeilenversionen in 10448587 Seiten gefunden
DETAIL: 0 tote Zeilenversionen können noch nicht entfernt werden.
Nicht entfernbare Zeilenversionen sind zwischen 37 und 2036 Byte lang.
Es gab 20121422 nicht verwendete Elementzeiger.
Der gesamte freie Speicherplatz (einschließlich der Versionen für entfernbare Zeilen) beträgt 0 Byte. 4944885 Seiten sind oder werden leer, einschließlich 0 am Ende der Tabelle. 4944885 Seiten mit 0 freien Bytes sind potenzielle Verschiebungsziele.
CPU 75,31 s / 29,59 u s verstrichen 877,79 s.
INFO: Der Index "pg_toast_16874_index" enthält jetzt 10475318 Zeilenversionen auf 179931 Seiten.
DETAIL: 23884 Indexzeilenversionen wurden entfernt.
101623 Indexseiten wurden gelöscht, 101623 sind derzeit wiederverwendbar.
CPU 1,35 s / 2,46 u s verstrichen 21,07 s.
REINDEXed die Tabelle, die etwas Speicherplatz freigab (~ 1 GB). Ich kann die Tabelle nicht CLUSTEREN, da auf der Festplatte nicht genügend Speicherplatz für den Prozess vorhanden ist, und ich warte darauf, die Tabelle vollständig neu zu erstellen, da ich herausfinden möchte, warum sie so viel größer ist als die entsprechenden Datenbanken.
Ich habe hier eine Abfrage aus dem PostgreSQL-Wiki ausgeführt - "Show Database Bloat" , und das bekomme ich:
aktuelle_Datenbank | Schemaname | Tabellenname | tbloat | verschwendete Bytes | iname | ibloat | Wastibytes ----------------- + ------------ + ------------------- ------------- + -------- + ------------- + ------------- -------------------- + -------- + -------------- ptrdb04 | paars00 | Zeitreihen | 1,0 | 0 | idx_timeseries_synchlevel | 0.0 | 0 ptrdb04 | paars00 | Zeitreihen | 1,0 | 0 | idx_timeseries_localavail | 0.0 | 0 ptrdb04 | paars00 | Zeitreihen | 1,0 | 0 | idx_timeseries_expirytime | 0.0 | 0 ptrdb04 | paars00 | Zeitreihen | 1,0 | 0 | idx_timeseries_expiry_null | 0.0 | 0 ptrdb04 | paars00 | Zeitreihen | 1,0 | 0 | uniq_localintid | 0.0 | 0 ptrdb04 | paars00 | Zeitreihen | 1,0 | 0 | pk_timeseries | 0,1 | 0 ptrdb04 | paars00 | idx_timeseries_expiry_null | 0,6 | 0 | ? | 0.0 | 0
Es sieht so aus, als würde die Datenbank diesen Speicherplatz überhaupt nicht als "leer" betrachten, aber ich sehe nur nicht, woher der gesamte Speicherplatz kommt!
Ich vermute, dass dieser Datenbankserver beschließt, 4-5x so viel Speicherplatz zu verwenden, um dieselben Datensätze zu speichern, die von den anderen Datenservern abgerufen wurden. Meine Frage lautet: Gibt es eine Möglichkeit, die physische Festplattengröße einer Zeile zu überprüfen? Ich möchte die Größe einer Zeile in dieser Datenbank mit einer anderen "gesunden" Datenbank vergleichen.
Vielen Dank für jede Hilfe, die Sie leisten können!
UPDATE 1
Am Ende habe ich die Tabelle aufgrund ihrer Größe aus einem ausgelagerten Schema neu erstellt (konnte sie nicht für einen weiteren Tag alleine lassen). Nach dem Synchronisieren der Daten über den Software-Synchronisierungsprozess betrug die TOAST-Tabelle ~ 35 GB. Ich konnte jedoch nur ~ 9 GB davon aus dieser Blob-Spalte entnehmen, die in Bezug auf die Werte am längsten sein sollte. Ich bin mir nicht sicher, woher die anderen 26 GB kommen. CLUSTERed, VACUUM FULLed und REINDEXed ohne Erfolg. Die postgresql.conf- Dateien zwischen dem lokalen und dem Remote-Datenserver sind genau gleich. Gibt es einen Grund, warum diese Datenbank versucht, jeden Datensatz mit einem größeren Speicherplatz auf der Festplatte zu speichern?
UPDATE 2 - Behoben
Ich habe mich schließlich entschlossen, die Datenbank von Grund auf neu zu erstellen und sogar die PostgreSQL84-Pakete auf dem System neu zu installieren. Der Datenbankpfad wurde neu initialisiert und die Tablespaces wurden gelöscht. Der Software-Synchronisierungsprozess eines Drittanbieters füllte die Tabellen neu und die endgültige Größe betrug ~ 12 GB ! Leider hilft dies in keiner Weise, die genaue Ursache des Problems zu lösen. Ich werde es mir ein oder zwei Tage lang ansehen und feststellen, ob es wesentliche Unterschiede bei der Behandlung der TOAST-Tabelle durch die revitalisierte Datenbank gibt, und diese Ergebnisse hier veröffentlichen.
Beziehungsgröße
ptrdb04=> SELECT nspname || '.' || relname AS "relation",
ptrdb04-> pg_size_pretty(pg_relation_size(C.oid)) AS "size"
ptrdb04-> FROM pg_class C
ptrdb04-> LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
ptrdb04-> WHERE nspname NOT IN ('pg_catalog', 'information_schema')
ptrdb04-> ORDER BY pg_relation_size(C.oid) DESC
ptrdb04-> LIMIT 2;
Beziehung | Größe
------------------------- + ---------
pg_toast . pg_toast_17269 | 18 GB
paars00 . warmstates | 1224 MB
( 2 Zeilen )
VACUUM VERBOSE ANALYZE timeseries;
INFO: "timeseries": 12699 entfernbare, 681961 nicht entfernbare Zeilenversionen in 58130 von 68382 Seiten gefunden DETAIL: 0 Dead Row-Versionen können noch nicht entfernt werden. Es gab 105847 nicht verwendete Elementzeiger. 0 Seiten sind völlig leer. CPU 0,83 s / 2,08 u s verstrichen 33,36 s. INFO: Staubsaugen "pg_toast.pg_toast_17269" INFO: Gescannter Index "pg_toast_17269_index" zum Entfernen von 2055849-Zeilenversionen DETAIL: CPU 0,37 s / 2,92 u s verstrichen 13,29 s. INFO: "pg_toast_17269": 2055849 Zeilenversionen auf 518543 Seiten entfernt DETAIL: CPU 8,60 s / 3,21 u s verstrichen 358,42 s. INFO: Der Index "pg_toast_17269_index" enthält jetzt 7346902 Zeilenversionen auf 36786 Seiten DETAIL: 2055849 Indexzeilenversionen wurden entfernt. 10410 Indexseiten wurden gelöscht, 5124 sind derzeit wiederverwendbar. CPU 0,00 s / 0,00 u s verstrichen 0,01 s. INFO: "pg_toast_17269": 1286128 entfernbare, 2993389 nicht entfernbare Zeilenversionen in 1257871 von 2328079 Seiten gefunden DETAIL: 0 Dead Row-Versionen können noch nicht entfernt werden. Es gab 18847 unbenutzte Artikelzeiger. 0 Seiten sind völlig leer. CPU 26,56 s / 13,04 u s verstrichen 714,97 s. INFO: Analyse von "paars00.timeseries" INFO: "Zeitreihen": 30000 von 68382 Seiten gescannt, die 360192 lebende Zeilen und 0 tote Zeilen enthalten; 30000 Zeilen in der Stichprobe, 821022 geschätzte Gesamtzeilen
Der einzige spürbare Unterschied nach dem Wiederherstellen (außer der Festplattennutzung) ist
INFO: "pg_toast_17269": 1286128 entfernbare, 2993389 nicht entfernbare Zeilenversionen gefundenwie @CraigRinger in einem Kommentar erwähnt. Die Anzahl der nicht entfernbaren Zeilen ist viel kleiner als zuvor.
Neue Frage: Können andere Tabellen die Größe einer anderen Tabelle beeinflussen? (über Fremdschlüssel und dergleichen) Die Neuerstellung der Tabelle hat nichts bewirkt, aber die Neuerstellung der gesamten Datenbank hat das Problem behoben.
quelle
Antworten:
Diese:
schlägt vor, dass das zugrunde liegende Problem darin besteht, dass diese Zeilen immer noch von etwas "gesehen" werden können, sodass sie nicht entfernt werden können.
Die Kandidaten dafür sind:
Verlorene vorbereitete Transaktionen. Überprüfen Sie
pg_catalog.pg_prepared_xacts
; es sollte leer sein. Auch laufenSHOW max_prepared_transactions
; es sollte Null melden.Lang laufende Sitzungen mit einer offenen, inaktiven Transaktion. In PostgreSQL 8.4 und höher sollte dies nur ein Problem für
SERIALIZABLE
Transaktionen sein. Suchen Siepg_catalog.pg_stat_activity
nach<IDLE> in transaction
Sitzungen.Höchstwahrscheinlich haben Sie einen Client, der Transaktionen während langer Leerlaufzeiten nicht festschreibt oder zurücksetzt.
Wenn sich herausstellt, dass dies nicht der Fall ist, würde ich als Nächstes eine Summe
octet_size
der einzelnen Spalten der interessierenden Tabelle erstellen . Vergleichen Sie das mit dempg_relation_size
Tisch und seinemTOAST
Beistelltisch. Wenn es einen großen Unterschied gibt, wird der Speicherplatz wahrscheinlich durch nicht mehr sichtbare Zeilen belegt, und Sie haben wahrscheinlich Probleme mit dem Aufblähen von Tabellen. Wenn sie sich ziemlich ähnlich sind, können Sie die Platznutzung eingrenzen, indem Sie die Oktettgrößen pro Spalte aufsummieren, die oberen 'n' Werte usw. erhalten.quelle
SELECT * FROM pg_stat_activity WHERE current_query LIKE '<IDLE>%';
denen etwa 30-40 Ergebnisse hervorgehen. Dies scheint jedoch ziemlich normal zu sein. Ich habe ein paar "gesunde" Server überprüft, und sie waren gleich.<IDLE> in transaction
, und nur dann , wenn sie haben (a) war im Leerlauf für eine Weile , und (b) verwendetSERIALIZABLE
Isolation oder Sie sind auf 8,3 oder älter.TOAST
Tabelle aufgebläht zu sein scheint. Übrigens, wenn SieVACUUM FULL
viel auf einem Server vor 9.0 verwendet haben, möchten Sie,REINDEX
wieVACUUM FULL
bei diesen Versionen, ein erhebliches Aufblähen des Index verursachen. Ich frage mich jetzt, ob jemand ein AbsurdesFILLFACTOR
auf den Toasttisch gelegt hat, obwohl das Sie nicht über den 10-fachen Platzverbrauch hinausgehen lassen sollte.Ich habe keine Ahnung, warum es aufgebläht ist. Aber ich habe etwas gesucht und vielleicht hat dieser Link einen Einblick: http://postgresql.1045698.n5.nabble.com/A-154-GB-table-swelled-to-527-GB-on-the-Slony-slave -How-to-compact-it-td5543034.html ... Es ist nicht Ihre genaue Situation, aber vielleicht ist es nah genug, um Ihnen zu helfen, dem Phantom -Aufblähen auf den Grund zu gehen.
Ich denke jedoch, dass die einzige Möglichkeit, diese Tabelle zu diesem Zeitpunkt zu komprimieren, darin besteht, sie zu CLUSTEREN. Da Sie wenig Speicherplatz haben, ist dies ein Problem.
Hier ist mein Vorschlag dafür: Erstellen Sie einen Tablespace auf einem anderen Laufwerk mit viel zusätzlichem Speicherplatz und weisen Sie dann Ihre Problemtabelle diesem Tablespace zu. PostgreSQL kopiert die Tabelle in den neuen Tabellenbereich (wahrscheinlich sperrt sie die Tabelle dabei, sodass Sie ein Wartungsfenster benötigen). Dann VACFULL die Tabelle (löscht den größten Teil des alten Speicherplatzes, den die Tabelle im Standardtabellenbereich belegt). Dann CLUSTER den Tisch und es sollte sich verdichten. Setzen Sie es dann wieder in den Standardtabellenbereich und führen Sie VACFULL erneut aus (um den nicht verwendeten Speicherplatz im neuen Tabellenbereich zu löschen).
quelle