У мене є екземпляр PostgreSQL 9.2, який працює на RHEL 6.3, 8-ядерній машині з 16 ГБ оперативної пам’яті. Сервер призначений для цієї бази даних. Зважаючи на те, що postgresql.conf за замовчуванням є досить консервативним щодо налаштувань пам'яті, я вважав, що це може бути хорошою можливістю дозволити Postgres використовувати більше пам'яті. На мій подив, дотримуючись поради щодо wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server значно сповільнив практично кожен запит, який я виконую, але це, очевидно, помітніше при складніших запитах.
Я також спробував запустити pgtune, який дав наступну рекомендацію з більш налаштованими параметрами, але це нічого не змінило. Він пропонує shared_buffers розміром 1/4 розміру оперативної пам’яті, що, здається, відповідає порадам в інших місцях (зокрема, щодо PG wiki).
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
Я спробував перевстановити всю базу даних після зміни налаштувань (використання reindex database
), але це не допомогло. Я розігрувався з спільними_буферами та work_mem. Поступово змінюючи їх із дуже консервативних значень за замовчуванням (128k / 1MB), поступово знижувалася продуктивність.
Я побіг EXPLAIN (ANALYZE,BUFFERS)
за кількома запитами, і винуватцем здається, що Hash Join значно повільніше. Мені незрозуміло, чому.
Щоб навести конкретний приклад, у мене є наступний запит. Він працює в ~ 2100 мс за конфігурацією за замовчуванням і ~ 3300 мс в конфігурації зі збільшеними розмірами буфера:
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)
для запиту вище:
- Буфери за замовчуванням: http://explain.depesz.com/s/xaHJ
- Більші буфери: http://explain.depesz.com/s/Plk
Питання полягає в тому, чому я спостерігаю зниження продуктивності, коли збільшую розміри буфера? Машині точно не вистачає пам'яті. Виділення, якщо для спільної пам'яті в ОС ( shmmax
і shmall
) встановлено дуже великі значення, це не повинно бути проблемою. Я також не отримую помилок у журналі Postgres. Я запускаю autovacuum у конфігурації за замовчуванням, але не очікую, що це має щось спільне з цим. Усі запити виконувались на одній машині за кілька секунд, лише зі зміненою конфігурацією (та перезапущеним PG).
Редагувати: Я щойно виявив один особливо цікавий факт: коли я виконую той самий тест на середині 2010 року iMac (OSX 10.7.5) також із Postgres 9.2.1 та 16 ГБ оперативної пам’яті, я не відчуваю уповільнення. Конкретно:
set work_mem='1MB';
select ...; // running time is ~1800 ms
set work_mem='96MB';
select ...' // running time is ~1500 ms
Коли я роблю абсолютно той самий запит (той, що був вище) з точно такими ж даними на сервері, я отримую 2100 мс з work_mem = 1 МБ і 3200 мс з 96 МБ.
У Mac є SSD, тому він зрозуміло швидший, але він демонструє поведінку, яку я очікував.
Дивіться також подальшу дискусію щодо pgsql-продуктивності .