it-swarm-eu.dev

PostgreSQL: Daten in den Speicher erzwingen

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?

34
Adam Matan

Sie könnten an einem der Mailinglistenthemen interessiert sein, es wird von Tom Lane (Core Dev) beantwortet:

[..] Aber meine Meinung ist, dass Leute, die denken, sie seien schlauer als ein LRU-Caching-Algorithmus, sich normalerweise irren. Wenn die Tabelle so häufig verwendet wird, bleibt sie in Ordnung. Wenn es nach einem LRU-Algorithmus nicht stark genug genutzt wird, um im Speicher zu bleiben, sollte der Speicherplatz möglicherweise wirklich für etwas anderes verwendet werden. [..]

Sie könnten auch an einer SO Frage: https://stackoverflow.com/questions/486154/postgresql-temporary-tables interessiert sein und vielleicht besser geeignet https://stackoverflow.com/questions/407006/need-to-load-the-whole-postgresql-database-into-the-ram

27
DrColossos

Postgres 9.4 hat endlich eine Erweiterung hinzugefügt, um Daten aus Beziehungen in den Betriebssystem- oder Datenbankpuffer-Cache (nach Ihrer Wahl) vorzuladen:

pg_prewarm

Dadurch kann die volle Betriebsleistung schneller erreicht werden.

Einmal in Ihrer Datenbank ausführen (detaillierte Anweisungen hier ):

CREATE EXTENSION pg_prewarm;

Dann ist es einfach, eine bestimmte Beziehung vorzuladen. Grundlegendes Beispiel:

SELECT pg_prewarm('my_tbl');

Findet die erste Tabelle mit dem Namen my_tbl im Suchpfad und lädt ihn in den Postgres-Puffercache

Oder:

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

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

Der Standardwert ist buffer, was den größten Einfluss hat (höhere Kosten, bester Effekt).

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

39

Im Allgemeinen können Sie, wenn Sie über genügend RAM verfügen), im Allgemeinen darauf vertrauen, dass der Datenbankdienst die Dinge, die Sie regelmäßig im RAM verwenden, gut aufbewahrt. Bei einigen Systemen können Sie darauf hinweisen, dass die Tabelle dies tun sollte Halten Sie immer in RAM (dies ist nützlich für kleinere Tabellen, die nicht oft verwendet werden, aber wenn sie verwendet werden, ist es wichtig, dass sie so schnell wie möglich reagieren), aber wenn pgsql solche Tabellen hat, gibt es Hinweise Sie müssen sehr vorsichtig sein, wenn Sie sie verwenden, da Sie weniger Speicher für das Zwischenspeichern anderer Elemente benötigen, damit Sie Ihre Anwendung möglicherweise insgesamt verlangsamen.

Wenn Sie den Seitencache der Datenbank beim Start vorbereiten möchten (z. B. nach einem Neustart oder einem anderen Wartungsvorgang, bei dem 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 der obigen Schritte sollte jede Daten- und Indexseite gelesen worden sein und befindet sich daher (zumindest vorerst) im Seiten-Cache RAM). Wir haben solche Skripte für unsere Anwendungsdatenbanken. Diese werden nach dem Neustart ausgeführt, damit die ersten Benutzer, die sich anschließend beim System anmelden, nicht langsamer reagieren. Sie sollten ein solches Skript besser von Hand schreiben, als die Datenbankdefinitionstabellen zu scannen (wie sys.objects/sys.indexes/sys.columns In MSSQL), dann können Sie die am häufigsten verwendeten Indizes selektiv scannen, anstatt alles zu scannen, was länger dauert.

4
David Spillett

Ich hatte ein ähnliches Problem:
Nach dem Neustart des Serverdienstes und dem Löschen aller eingelösten Daten wurden viele Abfragen, die beim ersten Mal aufgerufen wurden, aufgrund der spezifischen Komplexität der Abfragen sehr langsam, bis alle erforderlichen Indizes und Daten eingelöst wurden. Dies bedeutet, dass Benutzer beispielsweise jedes "Element" (Ausführungszeit 1-3 Sekunden) und zugehörige Daten aus 50 Millionen Zeilen einmal treffen müssen, damit Benutzer keine unerwünschten Verzögerungen mehr erleben. Es dauert die ersten 3 Stunden, bis Benutzer störende Probleme haben, bis die meisten verwendeten Daten eingelöst werden und Programme die Produktionsleistung auf höchstem Niveau ruinieren. Selbst dann enden 2 Tage mit einigen plötzlichen kurzen Verzögerungen, wenn weniger Daten zum ersten Mal abgerufen werden ... , für Statistikdaten etc.

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

1
LongBeard_Boldy

Ich verwende RamDrive von QSoft, das Benchmarking als schnellste Ramdisk für Windows war. Ich habe es gerade benutzt

initdb -D e:\data

dabei ist e:\der Ort der RamDisk.

0
David

Hmmm, vielleicht würde der Befehl COPY helfen. 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 cat <files> > /dev/null Auszuführen.

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 lautet also/path/to/pgsql/data/base/16384/24576 *

Sie möchten möglicherweise auch Indizes und Toasttabellen lesen und deren Oids auf die gleiche Weise abrufen.

Übrigens, warum brauchst du es? Ich glaube, postgresql und OS sind intelligent genug, um die heißesten Daten zwischenzuspeichern und gut zu pflegen. Cache-Effizienz.

0
rvs