Ich habe eine PostgreSQL 9.2-Instanz, die auf einem RHEL 6.3-Computer mit 8 Kernen und 16 GB RAM ausgeführt wird. Der Server ist dieser Datenbank zugeordnet. Angesichts der Tatsache, dass die Standardeinstellung für postgresql.conf in Bezug auf die Speichereinstellungen recht konservativ ist, hielt ich es für eine gute Idee, Postgres mehr Speicher zur Verfügung zu stellen. Zu meiner Überraschung hat das Befolgen von Ratschlägen auf wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server praktisch jede Abfrage, die ich ausführe, erheblich verlangsamt, was jedoch bei komplexeren Abfragen offensichtlich auffälliger ist.
Ich habe auch versucht, pgtune auszuführen, was die folgende Empfehlung mit mehr Parametern ergab, aber das hat nichts geändert. Es werden Shared_Buffer von 1/4 der RAM-Größe vorgeschlagen, was anscheinend mit anderen Empfehlungen (insbesondere in PG-Wiki) übereinstimmt.
default_statistics_target = 50
maintenance_work_mem = 960MB
constraint_exclusion = on
checkpoint_completion_target = 0.9
effective_cache_size = 11GB
work_mem = 96MB
wal_buffers = 8MB
checkpoint_segments = 16
shared_buffers = 3840MB
max_connections = 80
Ich habe versucht, die gesamte Datenbank nach dem Ändern der Einstellungen neu zu indizieren (mithilfe von reindex database
), aber das hat auch nicht geholfen. Ich habe mit shared_buffers und work_mem rumgespielt. Wenn Sie die sehr konservativen Standardwerte (128 KB / 1 MB) schrittweise ändern, sinkt die Leistung allmählich.
Ich habe EXPLAIN (ANALYZE,BUFFERS)
ein paar Fragen beantwortet und der Schuldige scheint zu sein, dass Hash Join bedeutend langsamer ist. Mir ist nicht klar warum.
Um ein konkretes Beispiel zu nennen: Ich habe die folgende Abfrage. Es wird in der Standardkonfiguration in ~ 2100 ms und in der Konfiguration mit erhöhten Puffergrößen in ~ 3300 ms ausgeführt:
select count(*) from contest c
left outer join contestparticipant cp on c.id=cp.contestId
left outer join teammember tm on tm.contestparticipantid=cp.id
left outer join staffmember sm on cp.id=sm.contestparticipantid
left outer join person p on p.id=cp.personid
left outer join personinfo pi on pi.id=cp.personinfoid
where pi.lastname like '%b%' or pi.firstname like '%a%';
EXPLAIN (ANALYZE,BUFFERS)
für die Abfrage oben:
- Standardpuffer: http://explain.depesz.com/s/xaHJ
- Größere Puffer: http://explain.depesz.com/s/Plk
Die Frage ist, warum ich eine verringerte Leistung beobachte, wenn ich die Puffergröße erhöhe. Der Maschine geht definitiv nicht der Speicher aus. Zuweisung, wenn Shared Memory im Betriebssystem ( shmmax
und shmall
) auf sehr große Werte gesetzt ist, sollte dies kein Problem sein. Ich bekomme auch keine Fehler im Postgres-Log. Ich verwende Autovacuum in der Standardkonfiguration, aber ich erwarte nicht, dass das irgendetwas damit zu tun hat. Alle Abfragen wurden im Abstand von wenigen Sekunden auf demselben Computer ausgeführt, nur mit geänderter Konfiguration (und neu gestartetem PG).
Edit: Ich fand gerade eine besonders interessante Tatsache: Wenn ich den gleichen Test auf meinem iMac Mitte 2010 (OSX 10.7.5) auch mit Postgres 9.2.1 und 16 GB RAM durchführe, spüre ich keine Verlangsamung. Speziell:
set work_mem='1MB';
select ...; // running time is ~1800 ms
set work_mem='96MB';
select ...' // running time is ~1500 ms
Wenn ich genau die gleiche Abfrage (die oben genannte) mit genau den gleichen Daten auf dem Server durchführe, erhalte ich 2100 ms mit work_mem = 1 MB und 3200 ms mit 96 MB.
Der Mac verfügt über eine SSD, ist also verständlicherweise schneller, zeigt aber ein Verhalten, das ich erwarten würde.
Siehe auch die nachfolgende Diskussion zu pgsql-performance .