Ich wechsle 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 dauerte es ~ 34 Sekunden, auf PG ~ 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 SQLite zu bringen (idealerweise nur durch Festlegen 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 sie auf die gesamte Datenbank angewendet werden, damit ich nicht alle Skripte geändert habe?)
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 idealerweise die Tricks beschreiben, um genau das zu tun, das Setup und die Nachteile dieser Tricks.
UPDATE: fsync = off
+ Die Zeit wurde full_page_writes = off
nur auf ~ 65 Sekunden (~ -16 Sekunden) verringert. Guter Start, aber weit vom Ziel von 34 entfernt.
UPDATE 2: Ich habe versucht, eine RAM-Disk zu verwenden, aber der Leistungsgewinn lag innerhalb einer Fehlergrenze. Scheint es also nicht wert zu sein.
UPDATE 3: * Ich habe den größten Engpass festgestellt und jetzt laufen meine Spezifikationen genauso schnell wie die von SQLite.
Das Problem war die Datenbankbereinigung, die das Abschneiden durchgeführt hat . Anscheinend ist SQLite dort viel zu schnell.
Um es zu "reparieren", öffne ich vor jedem Test eine Transaktion und rolle sie am Ende zurück.
Einige Zahlen für ~ 700 Tests.
- Kürzung: SQLite - 34s, PG - 76s.
- Transaktion: SQLite - 17s, PG - 18s.
2x Geschwindigkeitssteigerung für SQLite. 4x Geschwindigkeitssteigerung für PG.
quelle
Antworten:
Verwenden Sie zunächst immer die neueste Version von PostgreSQL. Leistungsverbesserungen kommen immer wieder, sodass Sie wahrscheinlich Ihre Zeit verschwenden, wenn Sie eine alte Version optimieren. Zum Beispiel verbessert PostgreSQL 9.2 die Geschwindigkeit von
TRUNCATE
und fügt natürlich nur Index-Scans hinzu. Auch kleinere Veröffentlichungen sollten immer befolgt werden; Siehe die Versionsrichtlinie .Nicht
Sie NICHT setzen einen Tabellen auf einer RAM - Disk oder einem anderen nicht-dauerhafte Lagerung .
Wenn Sie einen Tablespace verlieren, kann die gesamte Datenbank beschädigt und ohne großen Aufwand schwer zu verwenden sein. Dies hat nur einen geringen Vorteil gegenüber der Verwendung von
UNLOGGED
Tabellen und ohnehin viel RAM für den Cache.Wenn Sie wirklich ein Ramdisk-basiertes System wollen,
initdb
einen ganz neuen Cluster auf der Ramdisk, indeminitdb
Sie eine neue PostgreSQL-Instanz auf der Ramdisk erstellen, sodass Sie über eine vollständig verfügbare PostgreSQL-Instanz verfügen.PostgreSQL-Serverkonfiguration
Beim Testen können Sie Ihren Server für einen nicht dauerhaften, aber schnelleren Betrieb konfigurieren .
Dies ist eine der wenigen akzeptablen Verwendungen für die
fsync=off
Einstellung in PostgreSQL. Diese Einstellung weist PostgreSQL so ziemlich an, sich nicht mit geordneten Schreibvorgängen oder anderen unangenehmen Dingen zum Schutz der Datenintegrität und zum Schutz vor Unfällen zu befassen, und gibt PostgreSQL die Erlaubnis, Ihre Daten bei einem Stromausfall oder einem Absturz des Betriebssystems vollständig in den Papierkorb zu werfen.Es ist unnötig zu erwähnen,
fsync=off
dass Sie Pg niemals in der Produktion aktivieren sollten, es sei denn, Sie verwenden Pg als temporäre Datenbank für Daten, die Sie von einer anderen Stelle aus neu generieren können. Wenn und nur wenn Sie fsync ausschalten, können Sie es auchfull_page_writes
ausschalten, da es dann nichts mehr nützt. Beachten Sie diesfsync=off
undfull_page_writes
wenden Sie es auf Clusterebene an, damit alle Datenbanken in Ihrer PostgreSQL-Instanz betroffen sind .Für den Produktionsbetrieb können Sie möglicherweise einen verwenden
synchronous_commit=off
und festlegencommit_delay
, da Sie viele der gleichen Vorteile erhalten wiefsync=off
ohne das riesige Risiko der Datenkorruption. Sie haben ein kleines Fenster für den Verlust aktueller Daten, wenn Sie das asynchrone Festschreiben aktivieren - aber das war's.Wenn Sie die Möglichkeit haben, die DDL geringfügig zu ändern, können Sie auch
UNLOGGED
Tabellen in Seite 9.1+ verwenden, um die WAL-Protokollierung vollständig zu vermeiden und einen echten Geschwindigkeitsschub zu erzielen, wenn die Tabellen gelöscht werden, wenn der Server abstürzt. Es gibt keine Konfigurationsoption, mit der alle Tabellen nicht protokolliert werden können. Sie muss während festgelegt werdenCREATE TABLE
. Dies ist nicht nur gut zum Testen geeignet, sondern auch praktisch, wenn Sie Tabellen mit generierten oder unwichtigen Daten in einer Datenbank haben, die ansonsten Dinge enthält, die Sie für die Sicherheit benötigen.Überprüfen Sie Ihre Protokolle und prüfen Sie, ob Sie Warnungen vor zu vielen Kontrollpunkten erhalten. Wenn ja, sollten Sie Ihre checkpoint_segments erhöhen . Möglicherweise möchten Sie auch Ihr checkpoint_completion_target optimieren, um das Ausschreiben zu vereinfachen.
Tune
shared_buffers
Ihre Arbeit zu passen. Dies ist vom Betriebssystem abhängig, hängt davon ab, was sonst noch auf Ihrem Computer vor sich geht, und erfordert einige Versuche und Irrtümer. Die Standardeinstellungen sind äußerst konservativ. Möglicherweise müssen Sie das maximale Limit für gemeinsam genutzten Speicher des Betriebssystems erhöhen, wenn Sieshared_buffers
unter PostgreSQL 9.2 und darunter erhöhen . 9.3 und höher haben geändert, wie sie Shared Memory verwenden, um dies zu vermeiden.Wenn Sie nur ein paar Verbindungen verwenden, die viel Arbeit erledigen, erhöhen Sie diese
work_mem
, um ihnen mehr RAM zum Spielen für Sortierungen usw. zu geben. Beachten Sie, dass eine zu hohework_mem
Einstellung Probleme mit zu wenig Speicher verursachen kann, da dies nicht pro Sortierung der Fall ist pro Verbindung, sodass eine Abfrage viele verschachtelte Sortierungen haben kann. Sie müssen nur dann wirklich erhöhen,work_mem
wenn Sie sehen, dass Sortierungen auf die Festplatte gelangenEXPLAIN
oder mit derlog_temp_files
Einstellung (empfohlen) protokolliert werden. Ein höherer Wert kann jedoch auch dazu führen, dass Pg intelligentere Pläne auswählt.Wie in einem anderen Poster hier erwähnt, ist es ratsam, das xlog und die Haupttabellen / -indizes nach Möglichkeit auf separaten Festplatten zu speichern. Separate Partitionen sind ziemlich sinnlos, Sie möchten wirklich separate Laufwerke. Diese Trennung hat viel weniger Vorteile, wenn Sie
fsync=off
mitUNLOGGED
Tabellen arbeiten, und fast keine, wenn Sie Tabellen verwenden.Schließlich optimieren Sie Ihre Abfragen. Stellen Sie sicher , dass Ihre
random_page_cost
undseq_page_cost
die Leistung Ihres Systems widerspiegeln, sicherzustellen , dass Ihreffective_cache_size
richtig, usw. VerwendenEXPLAIN (BUFFERS, ANALYZE)
einzelnen Abfragepläne zu prüfen, und drehen Sie dasauto_explain
Modul auf alle langsame Abfragen zu melden. Sie können die Abfrageleistung häufig erheblich verbessern, indem Sie einen geeigneten Index erstellen oder die Kostenparameter anpassen.AFAIK Es gibt keine Möglichkeit, eine gesamte Datenbank oder einen Cluster als festzulegen
UNLOGGED
. Es wäre interessant, dies tun zu können. Fragen Sie auf der PostgreSQL-Mailingliste nach.Optimierung des Host-Betriebssystems
Es gibt einige Optimierungen, die Sie auch auf Betriebssystemebene vornehmen können. Die Hauptsache, die Sie möglicherweise tun möchten, ist, das Betriebssystem davon zu überzeugen, Schreibvorgänge nicht aggressiv auf die Festplatte zu übertragen, da es Ihnen wirklich egal ist, wann / ob sie es auf die Festplatte schaffen.
Unter Linux können Sie diese Steuerung mit dem virtuellen Speicher - Subsystem ‚s -
dirty_*
Einstellungen, wiedirty_writeback_centisecs
.Das einzige Problem bei der Optimierung der Rückschreibeinstellungen ist, dass ein Flush durch ein anderes Programm dazu führen kann, dass alle angesammelten PostgreSQL-Puffer ebenfalls geleert werden, was zu großen Verzögerungen führt, während beim Schreiben alles blockiert wird. Möglicherweise können Sie dies beheben, indem Sie PostgreSQL auf einem anderen Dateisystem ausführen. Einige Flushes können jedoch auf Geräte- oder Host-Ebene und nicht auf Dateisystemebene ausgeführt werden, sodass Sie sich nicht darauf verlassen können.
Diese Abstimmung erfordert wirklich das Herumspielen mit den Einstellungen, um zu sehen, was für Ihre Arbeitslast am besten funktioniert.
Auf neueren Kerneln möchten Sie möglicherweise sicherstellen, dass dieser
vm.zone_reclaim_mode
Wert auf Null gesetzt ist, da dies aufgrund von Interaktionen mit der Verwaltung von PostgreSQL zu schwerwiegenden Leistungsproblemen bei NUMA-Systemen führen kann (die meisten Systeme heutzutage)shared_buffers
.Abfrage- und Workload-Optimierung
Dies sind Dinge, die Codeänderungen erfordern; Sie passen möglicherweise nicht zu Ihnen. Einige Dinge können Sie möglicherweise anwenden.
Wenn Sie keine Arbeit 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 asynchrones Commit verwenden, ist dies weniger wichtig, wird aber dennoch dringend empfohlen.
Verwenden Sie nach Möglichkeit temporäre Tabellen. Sie generieren keinen WAL-Verkehr und sind daher für Einfügungen und Aktualisierungen viel schneller. Manchmal lohnt es sich, eine Reihe von Daten in eine temporäre Tabelle zu schlürfen, sie nach Bedarf zu bearbeiten und sie dann
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 Ihre Verbindung verlieren, wird die temporäre Tabelle gelöscht und keine andere Verbindung kann den Inhalt der temporären Tabelle (n) einer Sitzung sehen.Wenn Sie PostgreSQL 9.1 oder höher verwenden, können Sie
UNLOGGED
Tabellen für Daten verwenden, deren Verlust Sie sich leisten können, z. B. den Sitzungsstatus. Diese sind in verschiedenen Sitzungen sichtbar und werden zwischen Verbindungen beibehalten. Sie werden abgeschnitten, wenn der Server unsauber heruntergefahren wird, sodass sie nicht für alles verwendet werden können, was 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 SieTRUNCATE TABLE blah;
stattdessen; Es ist viel schneller, wenn Sie alle Zeilen in einer Tabelle ausgeben. Schneiden Sie viele Tabellen in einemTRUNCATE
Aufruf ab, wenn Sie können. Es gibt jedoch eine Einschränkung, wenn Sie immer wieder vieleTRUNCATES
kleine Tische spielen. siehe: Postgresql-KürzungsgeschwindigkeitWenn Sie keine Indizes für Fremdschlüssel haben, sind
DELETE
die Primärschlüssel, auf die diese Fremdschlüssel verweisen, fürchterlich langsam. Stellen Sie sicher, dass Sie solche Indizes erstellen, wenn Sie dies jemalsDELETE
von den referenzierten Tabellen erwarten . Indizes sind für nicht erforderlichTRUNCATE
.Erstellen Sie keine Indizes, die Sie nicht benötigen. Jeder Index hat Wartungskosten. Versuchen Sie, einen minimalen Satz von Indizes zu verwenden, und lassen Sie Bitmap-Index-Scans diese kombinieren, anstatt zu viele große, teure mehrspaltige Indizes zu verwalten. Wenn Indizes erforderlich sind, versuchen Sie zuerst, die Tabelle zu füllen, und erstellen Sie am Ende Indizes.
Hardware
Wenn Sie genug RAM haben, um die gesamte Datenbank zu speichern, ist dies ein großer Gewinn, wenn Sie es verwalten können.
Wenn Sie nicht über genügend RAM verfügen, ist der Speicher umso besser, je schneller er ist. Sogar eine billige SSD macht einen großen Unterschied gegenüber rotierendem Rost. Vertrauen Sie billigen SSDs für die Produktion nicht, sie sind oft nicht absturzsicher und fressen möglicherweise Ihre Daten.
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:
quelle
Verwenden Sie ein anderes Festplattenlayout:
postgresql.conf optimiert:
quelle
fsync=off
, dass sich das Speichern von pg_xlog auf einer separaten Festplatte nicht mehr wesentlich verbessert , wenn Sie bereits mit arbeiten.