Wie kann ich überprüfen, ob meine Datenbank mehr RAM benötigt?

11

Wie würden Sie überprüfen, ob Ihre Postgresql-DB-Instanz mehr RAM-Speicher benötigt, um ihre aktuellen Arbeitsdaten zu verarbeiten?

SDReyes
quelle
8
Sie müssen nicht überprüfen, Sie benötigen immer mehr RAM. :)
Alex Howansky
1
Keine Programmierfrage, ich stimme dafür, sie auf ServerFault zu verschieben.
GManNickG
1
Ich bin kein DBA, aber ich würde zunächst feststellen, dass häufig verwendete Abfragen am Rande einer Hash-Verknüpfung stehen, anstatt verschachtelte Schleifen zusammenzuführen. Sie können die Datenbankkonfiguration optimieren, die sich auch darauf auswirken kann, wie viel Speicher für eine bestimmte Abfrage verfügbar ist [überprüfen Sie die Dokumente oder senden Sie eine E-Mail an die Mailingliste, ist mein Vorschlag]. Es kann auch hilfreich sein, festzustellen, ob Sie über genügend RAM verfügen, um häufig verwendete Tabellen zwischengespeichert zu halten. Aber letztendlich könnten Sie mehr verwenden, es sei denn, Ihre GESAMTE Datenbank passt in den Arbeitsspeicher. :)

Antworten:

14

Wenn Sie nur unter Linux arbeiten, sollte Ihr physischer Gesamtspeicher größer sein als Ihre Datenbankgröße auf der Festplatte, um E / A zu minimieren. Schließlich befindet sich die gesamte Datenbank im Lesecache des Betriebssystems, und die E / A können nur Änderungen an der Festplatte vornehmen. Ich bevorzuge es, die DB-Größe durch Ausführen von "du -shc $ PGDATA / base" zu ermitteln - diese Methode fasst alle Datenbanken zu einer einzigen Zahl zusammen. Solange Sie größer sind, sollte es in Ordnung sein.

Darüber hinaus können Sie die Cache-Trefferquote von Heap- und Indexblockabrufen anzeigen. Diese messen die Trefferquote in den gemeinsam genutzten Puffern von PostgreSQL. Die Zahlen können etwas irreführend sein - auch wenn es sich möglicherweise um einen Fehler im Cache für gemeinsam genutzte Puffer handelt, kann es dennoch zu einem Treffer im Lese-Cache des Betriebssystems kommen. Trotzdem sind Treffer in gemeinsam genutzten Puffern immer noch günstiger als Treffer im Lesecache des Betriebssystems (die wiederum um einige Größenordnungen günstiger sind, als wenn sie auf die Festplatte zurückkehren müssen).

Um die Trefferquote der gemeinsam genutzten Puffer anzuzeigen, verwende ich diese Abfrage:

SELECT relname, heap_blks_read, heap_blks_hit,
    round(heap_blks_hit::numeric/(heap_blks_hit + heap_blks_read),3)
FROM pg_statio_user_tables
WHERE heap_blks_read > 0
ORDER BY 4
LIMIT 25;

Dies gibt Ihnen die 25 schlimmsten Straftäter, bei denen der Puffercache für alle Tabellen fehlt, bei denen mindestens ein Block von "Festplatte" abgerufen werden musste (dies kann entweder der Betriebssystem-Lese-Cache oder die tatsächliche Festplatten-E / A sein). Sie können den Wert in der WHERE-Klausel erhöhen oder eine weitere Bedingung für heap_blks_hit hinzufügen, um selten verwendete Tabellen herauszufiltern.

Dieselbe grundlegende Abfrage kann verwendet werden, um die Gesamtindex-Trefferquote pro Tabelle zu überprüfen, indem die Zeichenfolge "heap" global durch "idx" ersetzt wird. Schauen Sie sich pg_statio_user_indexes an, um eine Aufschlüsselung nach Index zu erhalten.

Ein kurzer Hinweis zu gemeinsam genutzten Puffern: Eine gute Faustregel für Linux ist, den Konfigurationsparameter shared_buffers auf 1/4 des Arbeitsspeichers, jedoch nicht mehr als 8 GB festzulegen . Dies ist keine feste Regel, sondern ein guter Ausgangspunkt für die Optimierung eines Servers. Wenn Ihre Datenbank nur 4 GB groß ist und Sie einen 32-GB-Server haben, sind 8 GB gemeinsam genutzte Puffer tatsächlich zu viel des Guten. Sie sollten dies auf 5 oder 6 GB einstellen können und dennoch Platz für zukünftiges Wachstum haben.

Matthew Wood
quelle
9

Ich habe diese SQL erstellt, um das Verhältnis von Tabellen zu Festplattentreffern anzuzeigen:

-- perform a "select pg_stat_reset();" when you want to reset counter statistics
with 
all_tables as
(
SELECT  *
FROM    (
    SELECT  'all'::text as table_name, 
        sum( (coalesce(heap_blks_read,0) + coalesce(idx_blks_read,0) + coalesce(toast_blks_read,0) + coalesce(tidx_blks_read,0)) ) as from_disk, 
        sum( (coalesce(heap_blks_hit,0)  + coalesce(idx_blks_hit,0)  + coalesce(toast_blks_hit,0)  + coalesce(tidx_blks_hit,0))  ) as from_cache    
    FROM    pg_statio_all_tables  --> change to pg_statio_USER_tables if you want to check only user tables (excluding postgres's own tables)
    ) a
WHERE   (from_disk + from_cache) > 0 -- discard tables without hits
),
tables as 
(
SELECT  *
FROM    (
    SELECT  relname as table_name, 
        ( (coalesce(heap_blks_read,0) + coalesce(idx_blks_read,0) + coalesce(toast_blks_read,0) + coalesce(tidx_blks_read,0)) ) as from_disk, 
        ( (coalesce(heap_blks_hit,0)  + coalesce(idx_blks_hit,0)  + coalesce(toast_blks_hit,0)  + coalesce(tidx_blks_hit,0))  ) as from_cache    
    FROM    pg_statio_all_tables --> change to pg_statio_USER_tables if you want to check only user tables (excluding postgres's own tables)
    ) a
WHERE   (from_disk + from_cache) > 0 -- discard tables without hits
)
SELECT  table_name as "table name",
    from_disk as "disk hits",
    round((from_disk::numeric / (from_disk + from_cache)::numeric)*100.0,2) as "% disk hits",
    round((from_cache::numeric / (from_disk + from_cache)::numeric)*100.0,2) as "% cache hits",
    (from_disk + from_cache) as "total hits"
FROM    (SELECT * FROM all_tables UNION ALL SELECT * FROM tables) a
ORDER   BY (case when table_name = 'all' then 0 else 1 end), from_disk desc

Geben Sie hier die Bildbeschreibung ein

Christian
quelle
1

Es funktioniert auch, wie in Heroku doc ​​gesagt:

SELECT
    'cache hit rate' AS name,
     sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) AS ratio
FROM pg_statio_user_tables;
Felipe
quelle