PostgreSQL: Daten in den Speicher zwingen

32

Gibt es eine systematische Möglichkeit, PostgreSQL zu zwingen, eine bestimmte Tabelle in den Speicher zu laden oder sie zumindest von der Festplatte zu lesen, damit sie vom System zwischengespeichert wird?

Adam Matan
quelle

Antworten:

25

Möglicherweise interessieren Sie sich für eines der Mailinglisten-Themen , das von Tom Lane (Core-Entwickler) beantwortet wird:

[..] Aber ich bin der Meinung, dass Leute, die sich für schlauer halten als ein LRU-Caching-Algorithmus, in der Regel falsch liegen. Wenn der Tisch stark ausgelastet ist, bleibt er in guter Erinnerung. Wenn es nicht stark genug genutzt wird, um nach einem LRU-Algorithmus im Speicher zu bleiben, sollte der Speicherplatz möglicherweise wirklich für etwas anderes verwendet werden. [..]

Sie könnten auch an einer SO-Frage interessiert sein: https://stackoverflow.com/questions/486154/postgresql-temporary-tables und möglicherweise geeigneter https://stackoverflow.com/questions/407006/need-to-load-the -Postgresql-Datenbank-in-den-RAM

DrColossos
quelle
1
+1 Die gleiche Idee gilt auch für andere RDBMS.
gbn
25
Ja und nein. Wir sperren einige Oracle-Tabellen im Arbeitsspeicher, weil wir wissen, dass sie möglicherweise nicht so oft verwendet werden, aber in der Situation, in der sie verwendet werden, ist die Latenz ein Killer. Ein DB sollte immer das letzte Wort des DBA erteilen (ein anderes Beispiel deutet auf den Abfrageoptimierer hin).
Gaius
35

Postgres 9.4 fügte schließlich eine Erweiterung hinzu, um Daten aus Relationen vorab in den Cache des Betriebssystems oder des Datenbankpuffers zu laden (nach Ihrer Wahl):

pg_prewarm

Dies ermöglicht ein schnelleres Erreichen der vollen Betriebsleistung.

Führen Sie einmal in Ihrer Datenbank aus (detaillierte Anweisungen hier ):

CREATE EXTENSION pg_prewarm;

Dann ist es einfach, eine bestimmte Relation vorzuladen. Einfaches Beispiel:

SELECT pg_prewarm('my_tbl');

Findet die erste my_tblim Suchpfad angegebene Tabelle und lädt sie in den Postgres-Puffercache

Oder:

SELECT pg_prewarm('my_schema.my_tbl', 'prefetch');

prefetchGibt asynchrone Prefetch-Anforderungen an das Betriebssystem aus, sofern dies unterstützt wird, oder gibt andernfalls einen Fehler aus. read liest den angeforderten Blockbereich; Im Gegensatz prefetchdazu ist dies synchron und wird auf allen Plattformen und Builds unterstützt, kann jedoch langsamer sein. bufferLiest den angeforderten Blockbereich in den Datenbankpuffer-Cache.

Die Standardeinstellung ist buffer, welche die größten Auswirkungen hat (höhere Kosten, beste Wirkung).

Lesen Sie das Handbuch für weitere Details , Zitate sind von dort.
Depesz hat auch darüber gebloggt .

Erwin Brandstetter
quelle
4

Wenn Sie über genügend RAM verfügen, können Sie sich im Allgemeinen darauf verlassen, dass der Datenbankdienst die Dinge, die Sie regelmäßig im RAM verwenden, ordnungsgemäß verwaltet. Bei einigen Systemen können Sie angeben, dass die Tabelle immer im RAM gespeichert werden soll (dies ist nützlich für kleinere Tabellen, die nicht häufig verwendet werden, aber wenn sie verwendet werden, ist es wichtig, dass sie so schnell wie möglich reagieren). Wenn pgsql jedoch solche Tabellenhinweise enthält Sie müssen sehr vorsichtig mit ihnen umgehen, da Sie den für die Zwischenspeicherung von anderen Elementen verfügbaren Arbeitsspeicher verringern, sodass Sie Ihre Anwendung möglicherweise insgesamt verlangsamen.

Wenn Sie den Seitencache der Datenbank beim Start vorbereiten möchten (z. B. nach einem Neustart oder einer anderen Wartungsoperation, bei der die Datenbank alles vergisst, was zwischengespeichert wird), schreiben Sie ein Skript, das Folgendes ausführt:

SELECT * FROM <table>
SELECT <primary key fields> FROM <table> ORDER BY <primary key fields>
SELECT <indexed fields> FROM <table> ORDER BY <indexed fields>

(Dieser letzte Schritt wird für jeden Index oder Kurs wiederholt. Achten Sie darauf, dass die Felder in der ORDER BY-Klausel in der richtigen Reihenfolge angezeigt werden.)

Nach dem Ausführen des obigen Befehls sollten alle Daten- und Indexseiten gelesen worden sein und sich (zumindest vorerst) im RAM-Seiten-Cache befinden. Wir haben solche Skripte für unsere Anwendungsdatenbanken, die nach dem Neustart ausgeführt werden, damit die ersten Benutzer, die sich danach am System anmelden, nicht langsamer reagieren. Sie sind besser dran , eine solche Skript von Hand schreiben, statt Scannen der db Definitionstabellen (wie sys.objects/ sys.indexes/ sys.columnsin MSSQL), dann können Sie selektiv die Indizes scannen , die meisten sind ziemlich häufig verwendet als das Scannen alles , die länger dauern wird.

David Spillett
quelle
3
Dies funktioniert zumindest unter PostgreSQL nicht. Ein kleiner Ringpuffer (256 KB) wird aus gemeinsam genutzten Puffern für sequentielle Scans zugewiesen, um zu verhindern, dass der gesamte Puffercache verwendet wird. Weitere Informationen finden Sie unter github.com/postgres/postgres/blob/master/src/backend/storage/… . Sie können dies überprüfen, indem Sie ein SELECT * aus einer großen Tabelle durchführen und dann die Tabelle pg_buffercache (mit der Erweiterung pg_buffercache) anzeigen.
hbn
@hbn hallo da, aber dieser kollege in diesem save thread sagt, dass es funktioniert - dba.stackexchange.com/a/36165/55752
scythargon
@scythargon wird möglicherweise im Cache des Betriebssystems abgelegt und nicht im PostgreSQL-Puffer-Cache abgelegt. Versuchen Sie, was ich oben vorgeschlagen habe, wenn Sie mir nicht glauben.
HBN
In Postgres 9.5 habe ich versucht, SELECT * FROM schema.tabledie gesamte 60-GB-Tabelle in meinen 100-GB-PostgreSQL-Puffercache zu laden.
Sudo
1

Ich hatte ein ähnliches Problem:
Nach dem Neustart des Serverdienstes und dem Löschen aller verrechneten Daten wurden viele Abfragen beim ersten Aufruf aufgrund der spezifischen Komplexität der Abfragen sehr langsam ausgeführt, bis alle erforderlichen Indizes und Daten verrechnet wurden. Dies bedeutet, dass Benutzer beispielsweise alle "Elemente" (1 bis 3 Sekunden Ausführungszeit) und die zugehörigen Daten aus 50 Millionen Zeilen einmal treffen müssen, damit keine unerwünschten Verzögerungen mehr auftreten. Es dauert die ersten 3 Stunden, bis Benutzer nervige Hänge feststellen, bis die meisten verwendeten Daten kassiert sind und Programme die Produktionsleistung auf höchstem Niveau ruinieren. Selbst dann enden 2 Tage mit ein paar plötzlichen kurzen Verzögerungen, wenn beim ersten Zugriff weniger Daten abgerufen werden ... , für Statistikdaten etc.

Um dies zu lösen, haben Sie ein kleines Python-Skript geschrieben, das Selects für am häufigsten verwendete Tabellen mit großen Indizes ausführt. Die Ausführung dauerte 15 Minuten, und es gab keine Leistungsverzögerungen.

LongBeard_Boldy
quelle
0

Hmmm, vielleicht wäre ein COPY-Befehl hilfreich. Führen Sie einfach COPY to stdout aus und lesen Sie daraus. Es ist möglich, dies mit pg_dump zu tun:

pg_dump -U <user> -t <table> <database> > /dev/null

Eine andere Möglichkeit besteht darin, alle Tabellendateien zu finden und auszuführen cat <files> > /dev/null.

Hier ist das Beispiel zum Abrufen von Tabellendateinamen:

# SELECT oid, datname FROM pg_database ;
  oid  |  datname  
-------+-----------                                                                                                                                          
<...>
 16384 | test
-- out of database is 16384
# SELECT oid, relname FROM pg_class WHERE relname like 'fn%';
  oid  | relname 
-------+---------
 24576 | fn
(1 row)
-- oid of our table is 24576

Die Datei (en) der Tabelle lauten also / path / to / pgsql / data / base / 16384/24576 *.

Sie möchten auch Indizes und Toast-Tabellen lesen und deren Oids auf die gleiche Weise erhalten.

BTW, warum brauchst du das? Ich glaube, Postgresql und OS ist klug genug, um die heißesten Daten zwischenzuspeichern und gut zu pflegen. Cache-Effizienz.

Wohnmobile
quelle
0

Ich benutze RAMDRIVE von QSoft, das wurde gebenchmarkt als der schnellste RAM - Disk für Windows. Ich habe gerade benutzt

initdb -D e:\data

Dabei ist e: \ der Ort der RamDisk.

David
quelle
5
PG unter Windows ist eine ziemlich mutige Wahl für einen Produktionsstandort, da es unter Windows viel langsamer ist als unter * nix (unabhängig vom RAM).
DrColossos