it-swarm.com.de

Optimieren Sie PostgreSQL für schnelle Tests

Ich wechsele von SQLite zu PostgreSQL für eine typische Rails Anwendung.

Das Problem ist, dass das Ausführen von Spezifikationen mit PG langsam wurde.
Auf SQLite hat es ~ 34 Sekunden gedauert, auf PG sind es ~ 76 Sekunden, was mehr als 2x langsamer ist .

Daher möchte ich jetzt einige Techniken anwenden, um die Leistung der Spezifikationen ohne Code-Änderungen auf das Niveau von SQLite zu bringen (idealerweise nur durch Einstellen der Verbindungsoptionen, was wahrscheinlich nicht möglich ist). .

Einige offensichtliche Dinge aus meinem Kopf sind:

  • RAM Disk (gutes Setup mit RSpec unter OSX wäre gut zu sehen)
  • Nicht protokollierte Tabellen (Kann es auf die gesamte Datenbank angewendet werden, damit nicht alle Skripte geändert werden?)

Wie Sie vielleicht verstanden haben, ist mir Zuverlässigkeit und der Rest egal (die DB ist hier nur ein Wegwerfartikel).
Ich muss das Beste aus dem PG herausholen und es so schnell wie möglich machen .

Die beste Antwort würde im Idealfall die Tricks beschreiben, um genau das zu tun, das Setup und die Nachteile dieser Tricks.

UPDATE: fsync = off + full_page_writes = off verkürzte die Zeit nur auf ~ 65 Sekunden (~ -16 Sekunden). Guter Start, aber weit vom Ziel von 34.

UPDATE 2: Ich habe versucht, RAM Datenträger zu verwenden, aber der Leistungsgewinn lag innerhalb einer Fehlerspanne. Es scheint sich zu lohnen.

UPDATE 3: * Ich habe den größten Engpass gefunden und jetzt laufen meine Spezifikationen so schnell wie die von SQLite.

Das Problem war die Datenbankbereinigung, bei der die Kürzung durchgeführt wurde . Anscheinend ist SQLite dort viel zu schnell.

Um das Problem zu beheben, öffne ich vor jedem Test eine Transaktion und setze sie am Ende zurück.

Einige Zahlen für ~ 700 Tests.

  • Kürzung: SQLite - 34s, PG - 76s.
  • Transaktion: SQLite - 17s, PG - 18s.

2x Geschwindigkeitserhöhung für SQLite. 4x Geschwindigkeitserhöhung für PG.

194

Verwenden Sie immer die neueste Version von PostgreSQL. Die Leistung wird ständig verbessert, sodass Sie wahrscheinlich Ihre Zeit verschwenden, wenn Sie eine alte Version optimieren. Zum Beispiel verbessert PostgreSQL 9.2 die Geschwindigkeit von TRUNCATE erheblich und fügt natürlich nur Index-Scans hinzu. Auch kleinere Releases sollten immer beachtet werden. Siehe die Versionsrichtlinie .

Nicht

Setzen Sie NICHT einen Tablespace auf eine RAM-Disk oder einen anderen nicht dauerhaften Speicher .

Wenn Sie einen Tablespace verlieren, ist möglicherweise die gesamte Datenbank beschädigt und ohne nennenswerten Arbeitsaufwand schwer zu verwenden. Dies hat nur einen geringen Vorteil gegenüber der Verwendung von UNLOGGED -Tabellen und der ohnehin großen Menge an RAM für den Cache.

Wenn Sie wirklich ein auf einer Ramdisk basierendes System wollen, initdb erstellen Sie einen neuen Cluster auf der Ramdisk, indem Sie initdb eine neue PostgreSQL-Instanz auf der Ramdisk erstellen, sodass Sie eine vollständig verfügbare PostgreSQL-Instanz haben.

PostgreSQL-Serverkonfiguration

Beim Testen können Sie Ihren Server für einen nicht dauerhaften, aber schnelleren Betrieb konfigurieren .

Dies ist eine der wenigen zulässigen Verwendungen für die Einstellung fsync=off in PostgreSQL. Diese Einstellung weist PostgreSQL an, sich nicht mit geordneten Schreibvorgängen oder anderen unangenehmen Datenintegritäts- und Absturzsicherungsmaßnahmen zu befassen, und gibt PostgreSQL die Erlaubnis, Ihre Daten vollständig in den Papierkorb zu werfen, wenn Sie die Stromversorgung verlieren oder ein Betriebssystem abstürzen.

Selbstverständlich sollten Sie in der Produktion niemals fsync=off Aktivieren, es sei denn, Sie verwenden Pg als temporäre Datenbank für Daten, die Sie aus anderen Quellen neu generieren können. Wenn und nur wenn Sie fsync ausschalten, können Sie auch full_page_writes ausschalten, da dies dann nichts mehr bringt. Beachten Sie, dass fsync=off Und full_page_writes Auf der Ebene Cluster gelten, sodass sie alle Datenbanken in Ihrer PostgreSQL-Instanz betreffen.

Für die Produktion können Sie möglicherweise synchronous_commit=off Verwenden und einen commit_delay Festlegen, da Sie viele der gleichen Vorteile wie bei fsync=off Erhalten, ohne dass das Risiko einer riesigen Datenkorruption besteht. Wenn Sie die asynchrone Festschreibung aktivieren, kann es zu einem kleinen Datenverlust kommen - aber das war's.

Wenn Sie die Option haben, die DDL geringfügig zu ändern, können Sie auch UNLOGGED -Tabellen in Pg 9.1+ verwenden, um die WAL-Protokollierung vollständig zu vermeiden und eine echte Geschwindigkeitssteigerung zu erzielen, und zwar auf Kosten der Tabellen, die gelöscht werden, wenn der Server abstürzt. Es gibt keine Konfigurationsoption, mit der alle Tabellen nicht protokolliert werden können. Sie muss bei CREATE TABLE Festgelegt werden. Dies ist nicht nur zum Testen gut, sondern auch praktisch, wenn Sie Tabellen mit generierten oder unwichtigen Daten in einer Datenbank haben, die ansonsten Informationen enthalten, die Sie für die Sicherheit benötigen.

Überprüfen Sie Ihre Protokolle und prüfen Sie, ob Warnungen zu vielen Checkpoints angezeigt werden. Wenn ja, sollten Sie Ihre checkpoint_segments erhöhen. Möglicherweise möchten Sie auch Ihr checkpoint_completion_target optimieren, um das Ausschreiben zu glätten.

Passen Sie shared_buffers An Ihre Arbeitsbelastung an. Dies ist vom Betriebssystem abhängig, hängt von den anderen Vorgängen auf Ihrem Computer ab und erfordert einige Versuche. Die Standardeinstellungen sind äußerst konservativ. Unter PostgreSQL 9.2 und niedriger müssen Sie möglicherweise das maximale Limit für den gemeinsam genutzten Speicher des Betriebssystems erhöhen, wenn Sie shared_buffers Erhöhen. 9.3 und höher haben geändert, wie Shared Memory verwendet wird, um dies zu vermeiden.

Wenn Sie nur ein paar Verbindungen verwenden, die viel Arbeit erledigen, erhöhen Sie work_mem, Um ihnen mehr RAM zum Spielen zu geben. Achten Sie darauf, dass ein work_mem Kann zu Problemen mit zu wenig Arbeitsspeicher führen, da es sich nicht um eine Verbindung handelt, sondern um eine Sortierung, sodass eine Abfrage mehrere verschachtelte Sortierungen haben kann. Sie müssen nur wirklichwork_mem Erhöhen, wenn Sie feststellen, dass in EXPLAIN oder mit dem log_temp_files Einstellung (empfohlen), aber ein höherer Wert kann Pg auch intelligentere Pläne auswählen lassen.

Wie von einem anderen Poster hier gesagt, ist es ratsam, das xlog und die Haupttabellen/-indizes auf separaten Festplatten abzulegen, wenn dies möglich ist. Separate Partitionen sind ziemlich sinnlos. Sie möchten wirklich separate Laufwerke. Diese Trennung hat viel weniger Vorteile, wenn Sie mit fsync=off - und fast keinen, wenn Sie UNLOGGED - Tabellen verwenden.

Optimieren Sie schließlich Ihre Abfragen. Stellen Sie sicher, dass Ihr random_page_cost Und seq_page_cost Die Leistung Ihres Systems widerspiegeln, dass Ihr effective_cache_size Korrekt ist usw. Verwenden Sie EXPLAIN (BUFFERS, ANALYZE), um einzelne Abfragepläne zu untersuchen, und Aktivieren Sie das Modul auto_explain, um alle langsamen Abfragen zu melden. Sie können die Abfrageleistung häufig erheblich verbessern, indem Sie einfach einen geeigneten Index erstellen oder die Kostenparameter optimieren.

AFAIK: Es gibt keine Möglichkeit, eine gesamte Datenbank oder einen Cluster als UNLOGGED festzulegen. Es wäre interessant, das zu können. Fragen Sie in der PostgreSQL-Mailingliste nach.

Optimierung des Host-Betriebssystems

Es gibt auch einige Optimierungen, die Sie auf Betriebssystemebene vornehmen können. Die Hauptsache, die Sie vielleicht tun möchten, ist, das Betriebssystem davon zu überzeugen, Schreibvorgänge nicht aggressiv auf die Festplatte zu schreiben, da es Ihnen wirklich egal ist, wann/ob sie es auf die Festplatte schaffen.

Unter Linux können Sie dies mit den Einstellungen des virtuellen Speichersubsystemsdirty_* Wie dirty_writeback_centisecs Steuern.

Das einzige Problem beim Optimieren der Rückschreibeinstellungen, das zu locker ist, besteht darin, dass ein Leeren durch ein anderes Programm dazu führen kann, dass alle von PostgreSQL akkumulierten Puffer ebenfalls geleert werden, was zu großen Verzögerungen führt, während alle Schreibvorgänge blockiert werden. Möglicherweise können Sie dies abmildern, indem Sie PostgreSQL auf einem anderen Dateisystem ausführen. Einige Löschvorgänge können jedoch auf Geräteebene oder auf Gesamthostebene und nicht auf Dateisystemebene ausgeführt werden, sodass Sie sich nicht darauf verlassen können.

Für diese Optimierung müssen Sie erst einmal mit den Einstellungen herumspielen, um herauszufinden, was für Ihre Arbeitsbelastung am besten geeignet ist.

Bei neueren Kerneln möchten Sie möglicherweise sicherstellen, dass vm.zone_reclaim_mode Auf Null gesetzt ist, da dies aufgrund von Interaktionen mit der PostgreSQL-Verwaltung shared_buffers Zu schwerwiegenden Leistungsproblemen bei NUMA-Systemen führen kann (die meisten Systeme heutzutage). .

Abfrage- und Workload-Optimierung

Dies sind Dinge, die Codeänderungen erfordern; Sie passen vielleicht nicht zu dir. Einige sind Dinge, die Sie möglicherweise anwenden können.

Wenn Sie nicht in größere Transaktionen stapeln, starten Sie. Viele kleine Transaktionen sind teuer, daher sollten Sie Dinge stapeln, wann immer dies möglich und praktisch ist. Wenn Sie async commit verwenden, ist dies weniger wichtig, wird jedoch dringend empfohlen.

Verwenden Sie nach Möglichkeit temporäre Tabellen. Sie generieren keinen WAL-Verkehr und sind daher viel schneller für Einfügungen und Aktualisierungen. Manchmal lohnt es sich, ein paar Daten in eine temporäre Tabelle zu schlürfen, sie nach Bedarf zu bearbeiten und dann mit einem INSERT INTO ... SELECT ... In die endgültige Tabelle zu kopieren. Beachten Sie, dass temporäre Tabellen pro Sitzung sind. Wenn Ihre Sitzung endet oder Sie die Verbindung verlieren, wird die temporäre Tabelle geschlossen, und keine andere Verbindung kann den Inhalt der temporären Tabelle (n) einer Sitzung sehen.

Wenn Sie PostgreSQL 9.1 oder neuer verwenden, können Sie UNLOGGED Tabellen für Daten verwenden, die Sie möglicherweise verlieren möchten, z. B. den Sitzungsstatus. Diese werden über verschiedene Sitzungen hinweg angezeigt und zwischen Verbindungen beibehalten. Sie werden abgeschnitten, wenn der Server unsauber heruntergefahren wird, sodass sie für nichts verwendet werden können, das Sie nicht neu erstellen können. Sie eignen sich jedoch hervorragend für Caches, materialisierte Ansichten, Statustabellen usw.

Im Allgemeinen nicht DELETE FROM blah;. Verwenden Sie stattdessen TRUNCATE TABLE blah;; Es geht viel schneller, wenn Sie alle Zeilen in einer Tabelle sichern. Kürzen Sie nach Möglichkeit viele Tabellen in einem TRUNCATE - Aufruf. Es gibt jedoch eine Einschränkung, wenn Sie immer wieder viele TRUNCATES kleine Tische spielen. siehe: Postgresql Trunkierungsgeschwindigkeit

Wenn Sie keine Indizes für Fremdschlüssel haben, sind DELETE s mit den von diesen Fremdschlüsseln referenzierten Primärschlüsseln furchtbar langsam. Stellen Sie sicher, dass Sie solche Indizes erstellen, wenn Sie jemals erwarten, dass DELETE aus den referenzierten Tabellen stammt. Indizes sind für TRUNCATE nicht erforderlich.

Erstellen Sie keine Indizes, die Sie nicht benötigen. Jeder Index hat Wartungskosten. Verwenden Sie möglichst wenige Indizes, und lassen Sie Bitmap-Index-Scans kombinieren, anstatt zu viele große, teure mehrspaltige Indizes zu verwalten. Wenn Indizes erforderlich sind, versuchen Sie zunächst, die Tabelle zu füllen, und erstellen Sie dann am Ende Indizes.

Hardware

Es ist ein Riesengewinn, wenn Sie über genügend RAM verfügen, um die gesamte Datenbank zu speichern.

Wenn Sie nicht über genügend RAM verfügen, können Sie den schnelleren Speicher besser nutzen. Sogar eine billige SSD macht einen großen Unterschied gegenüber Rust. Vertrauen Sie jedoch keinen billigen SSDs für die Produktion, sie sind oft nicht absturzsicher und können Ihre Daten verschlingen.

Lernen

Greg Smiths Buch PostgreSQL 9.0 High Performance bleibt relevant, obwohl auf eine etwas ältere Version verwiesen wird. Es sollte eine nützliche Referenz sein.

Treten Sie der allgemeinen PostgreSQL-Mailingliste bei und folgen Sie ihr.

Lesen:

268
Craig Ringer

Verwenden Sie ein anderes Festplattenlayout:

  • andere Festplatte für $ PGDATA
  • andere Festplatte für $ PGDATA/pg_xlog
  • unterschiedlicher Datenträger für temporäre Dateien (pro Datenbank $ PGDATA/base // pgsql_tmp) (siehe Hinweis zu work_mem)

postgresql.conf optimiert:

  • shared_memory: 30% der verfügbaren RAM aber nicht mehr als 6 bis 8 GB. Es scheint besser zu sein, weniger Shared Memory (2 GB - 4 GB) für schreibintensive Workloads zu haben
  • work_mem: hauptsächlich für ausgewählte Abfragen mit Sortierungen/Aggregationen. Dies gilt pro Verbindungseinstellung, und die Abfrage kann diesen Wert mehrmals zuweisen. Wenn die Daten nicht passen, wird die Festplatte verwendet (pgsql_tmp). Aktivieren Sie "EXPLAIN ANALYSE", um festzustellen, wie viel Speicher Sie benötigen
  • fsync und synchronous_commit: Standardwerte sind sicher, aber wenn Sie Datenverlust tolerieren können, können Sie sie deaktivieren
  • random_page_cost: Wenn Sie über eine SSD oder ein schnelles RAID-Array verfügen, können Sie diese auf 2.0 (RAID) oder sogar auf 1.1 (SSD) senken
  • checkpoint_segments: Sie können höher als 32 oder 64 gehen und checkpoint_completion_target auf 0.9 ändern. Ein niedrigerer Wert ermöglicht eine schnellere Wiederherstellung nach einem Absturz
9
mys