Meine Frage besteht aus 2 Teilen.
- Gibt es eine Möglichkeit, die anfängliche Größe einer Datenbank in PostgreSQL festzulegen?
- Wenn nicht, wie gehen Sie mit der Fragmentierung um, wenn die Datenbank mit der Zeit wächst?
Ich bin kürzlich von MSSQL zu Postgres migriert, und eines der Dinge, die wir in der MSSQL-Welt beim Erstellen einer Datenbank getan haben, war die Angabe der Anfangsgröße der Datenbank und des Transaktionsprotokolls. Dies verringert die Fragmentierung und erhöht die Leistung, insbesondere wenn die "normale" Größe der Datenbank im Voraus bekannt ist.
Die Leistung meiner Datenbank nimmt mit zunehmender Größe ab. Zum Beispiel dauert die Arbeit, die ich durchführe, normalerweise 10 Minuten. Wenn die Datenbank wächst, nimmt diese Zeit zu. Wenn Sie eine VACUUM-, VACUUM FULL- und VACUUM FULL-ANALYSE durchführen, scheint sich das Problem nicht zu lösen. Durch das Stoppen der Datenbank, das De-Fragmentieren des Laufwerks und die anschließende VACUUM FULL ANALYSE wird die Leistung meines Tests auf die ursprünglichen 10 Minuten zurückgesetzt. Dies lässt mich vermuten, dass Fragmentierung mich schmerzt.
Ich konnte keinen Verweis auf die Reservierung von Tablespace / Datenbank in Postgres finden. Entweder verwende ich die falsche Terminologie und finde nichts, oder es gibt eine andere Möglichkeit, die Fragmentierung des Dateisystems in Postgres zu verringern.
Irgendwelche Hinweise?
Die Lösung
Die gelieferten Antworten bestätigten, was ich vermutet hatte. PostgreSQL speichert die Datenbank über mehrere Dateien hinweg. Auf diese Weise kann die Datenbank ohne Fragmentierungsprobleme erweitert werden. Das Standardverhalten besteht darin, diese Dateien bis zum Rand mit Tabellendaten zu packen. Dies ist gut für Tabellen, die sich selten ändern, aber schlecht für Tabellen, die häufig aktualisiert werden.
PostgreSQL verwendet MVCC , um gleichzeitig auf Tabellendaten zuzugreifen. Bei diesem Schema wird bei jeder Aktualisierung eine neue Version der aktualisierten Zeile erstellt (dies kann über den Zeitstempel oder die Versionsnummer erfolgen, wer weiß?). Die alten Daten werden nicht sofort gelöscht, sondern zum Löschen markiert. Die tatsächliche Löschung erfolgt, wenn eine VACUUM-Operation ausgeführt wird.
Wie hängt das mit dem Füllfaktor zusammen? Der Standardfüllfaktor für Tabellen von 100 füllt die Tabellenseiten vollständig aus, was wiederum bedeutet, dass auf der Tabellenseite kein Platz für aktualisierte Zeilen vorhanden ist, dh aktualisierte Zeilen werden auf einer anderen Tabellenseite als in der ursprünglichen Zeile abgelegt. Das ist schlecht für die Leistung, wie meine Erfahrung zeigt. Da meine Übersichtstabellen sehr häufig aktualisiert werden (bis zu 1500 Zeilen / Sek.), Habe ich einen Füllfaktor von 20 festgelegt, dh 20% der Tabelle sind für eingefügte Zeilendaten und 80% für Aktualisierungsdaten. Dies mag zwar übertrieben erscheinen, aber der große Platz, der für aktualisierte Zeilen reserviert ist, bedeutet, dass die aktualisierten Zeilen auf derselben Seite wie das Original bleiben und die Tabellenseite zum Zeitpunkt der Ausführung des Autovacuum-Daemons zum Entfernen veralteter Zeilen nicht voll ist.
Um meine Datenbank zu "reparieren", habe ich Folgendes getan.
- Setzen Sie den Füllfaktor meiner Übersichtstabellen auf 20. Sie können dies zum Zeitpunkt der Erstellung tun, indem Sie einen Parameter an CREATE TABLE übergeben oder hinterher über ALTER TABLE. Ich habe den folgenden Befehl plpgsql ausgegeben:
ALTER TABLE "my_summary_table" SET (fillfactor = 20);
- Erstellte ein VACUUM FULL, da dieses eine komplett neue Version der Tabellendatei schreibt und somit implizit eine neue Tabellendatei mit dem neuen Füllfaktor schreibt .
Wenn ich meine Tests erneut durchführe, sehe ich keinen Leistungsabfall, selbst wenn die Datenbank so groß ist, wie ich es für viele Millionen Zeilen benötige.
TL; DR - Dateifragmentierung war nicht die Ursache, sondern eine Fragmentierung des Tabellenbereichs. Dies wird durch die Anpassung des Füllfaktors der Tabelle an Ihren speziellen Anwendungsfall verringert.
quelle
Antworten:
Wenn Sie den Server mit der Option --with-segsize kompilieren, kann dies hilfreich sein, wenn Ihre Tabelle mehr Platz beansprucht als ein Gig und Ihr Dateisystem eine einzelne Datei verarbeiten kann, die über einem Gig liegt. Wenn Sie 20 Gigs einfügen, müssen 20 Dateien erstellt werden, wenn Sie diesen Schalter nicht verwenden. Wenn Ihr Dateisystem eine Datei über einen Gig hinweg verarbeiten kann, können Sie sie einfach auf einen großen Wert einstellen.
Schauen Sie sich CLUSTER http://www.postgresql.org/docs/9.1/static/sql-cluster.html und FILLFACTOR http://www.postgresql.org/docs/9.1/static/sql-createtable.html an . http://www.postgresql.org/docs/9.1/static/sql-createindex.html
Beachten Sie, dass FILLFACTOR sowohl auf Tabellen als auch auf Indizes angewendet werden kann.
quelle
Es gibt noch etwas im Spiel, das Ihre Gleichungen noch nicht eingegeben hat: HEISSES Update . Verwandte Antworten:
Das Einstellen
FILLFACTOR
auf so niedrig, wie20
es übertrieben erscheint. Es bläht den Tisch auf das Fünffache seiner Größe auf. Wenn HOT-Updates funktionieren, sollten Sie normalerweise nicht so tief gehen müssen .Es gibt Ausnahmen: HOT-Updates können nur tote Tupel aus vorherigen Transaktionen wiederverwenden , nicht aus denselben oder gleichzeitig ausgeführten . Daher kann eine hohe gleichzeitige Last oder lange Transaktionen, bei denen dieselben Zeilen wiederholt aktualisiert werden, eine so niedrige (oder sogar niedrigere) Einstellung rechtfertigen.
Wenn Sie große Aktualisierungen haben, die große Teile der Tabelle auf einmal ändern, möchten Sie diese möglicherweise in ein paar Abschnitte aufteilen. Im Idealfall ändern Sie nur so viele Zeilen auf einmal, wie lokal auf die Datenseite passen. Aber das ist schwer einzuschätzen und zu regulieren.
Beachten Sie, dass HOT-Aktualisierungen nur funktionieren, wenn die geänderten Spalten in keiner Weise in Indizes einbezogen sind (weder als Daten noch als Bedingung in einem Teilindex). Möglicherweise blockieren Sie HOT-Updates mit Indizes für aktualisierte Spalten. Wenn diese entbehrlich sind, erhalten Sie ohne sie möglicherweise eine bessere Gesamtleistung.
Schließlich können Sie die Autovakuum-Parameter pro Tabelle einstellen . Sie könnten auf stark aktualisierte Tabellen mit aggressiven Einstellungen abzielen, die eine etwas engere Packung von Zeilen ermöglichen als nur
FILLFACTOR 20
.quelle
Wenn es sich bei Ihrem Problem um eine Dateifragmentierung handelt, ist dies nicht der Fall. In Postgres erhält jede Tabelle eine eigene Datei oder eine Reihe von Dateien im Dateisystem, wenn TOAST verwendet wird. Dies unterscheidet sich beispielsweise von Oracle (oder anscheinend von MS-SQL), in dem Sie Tabellenbereichsdateien in vorgefertigter Größe erstellen, in die Ihre Tabellen abgelegt werden. Allerdings kann es auch dort zu Problemen bei der Fragmentierung des Dateisystems kommen, wenn die Tabellenbereichsdateien erweitert werden oder das Dateisystem erweitert wird anfangs stark fragmentiert.
Was Ihre zweite Frage betrifft ... Ich habe keine Ahnung, wie ich mit der Fragmentierung des Dateisystems sauber umgehen soll, da MS-Windows das einzige Betriebssystem ist, bei dem Fragmentierungsprobleme aufgetreten sind und ich MS-Windows nur absolut ausführen kann muss in diesen Tagen sein. Möglicherweise könnte das Platzieren der Datenbankdateien auf eigenen Datenträgern zu einem gewissen Grad Abhilfe schaffen.
quelle