PostgreSQL: настройка производительности
Subsections
- 2.1 Используемая память
- 2.1.1 Общий буфер сервера: shared_buffers
- 2.1.2 Память для сортировки результата запроса: sort_mem
- 2.1.3 Память для работы команды VACUUM: vacuum_mem
- 2.2 Журнал транзакций и контрольные точки
- 2.2.1 fsync и стоит ли его трогать
- 2.2.2 Уменьшение количества контрольных точек
- 2.2.3 Прочие параметры
- 2.3 Free Space Map: как избавиться от VACUUM FULL
- 2.4 Прочие настройки
- 2.5 Диски и файловые системы
2 Настройка сервера
В этом разделе описаны рекомендуемые значения параметров, влияющих на производительность СУБД. Эти параметры обычно устанавливаются в конфигурационном файле postgresql.conf и влияют на все базы в текущей установке.
2.1 Используемая память
2.1.1 Общий буфер сервера: shared_buffers
PostgreSQL не читает данные напрямую с диска и не пишет их сразу на диск. Данные загружаются в общий буфер сервера, находящийся в разделяемой памяти, серверные процессы читают и пишут блоки в этом буфере, а затем уже изменения сбрасываются на диск.
Если процессу нужен доступ к таблице, то он сначала ищет нужные блоки в общем буфере. Если блоки присутствуют, то он может продолжать работу, если нет -- делается системный вызов для их загрузки. Загружаться блоки могут как из файлового кэша ОС, так и с диска, и эта операция может оказаться весьма «дорогой».
Если объём буфера недостаточен для хранения часто используемых рабочих данных, то они будут постоянно писаться и читаться из кэша ОС или с диска, что крайне отрицательно скажется на производительности.
Объём задаётся параметром shared_buffers в файле postgresql.conf. Единица измерения параметра -- блоки величиной 8 кБ. По умолчанию значение параметра составляет 641, что соответствует 512 кБ памяти. Это весьма мало, и для полноценной работы значение параметра следует увеличить.
В то же время не следует устанавливать это значение слишком большим: PostgreSQL полагается на то, что операционная система кэширует файлы (см. пункт 2.4.1), и не старается дублировать эту работу. Кроме того, чем больше памяти будет отдано под буфер, тем меньше останется операционной системе и другим приложениям, что может привести к своппингу.
В качестве начальных значений можете попробовать следующие:
- Начните с 4 МБ (512) для рабочей станции
- Средний объём данных и 256-512 МБ доступной памяти: 16-32 МБ (2048-4096)
- Большой объём данных и 1-4 ГБ доступной памяти: 64-256 МБ (8192-32768)
Обратите внимание, что память под буфер выделятся при запуске сервера, и её объём при работе не изменяется. Учтите также, что настройки ядра операционной системы могут не дать вам выделить большой объём памяти. В руководстве администратора PostgreSQL описано, как можно изменить эти настройки: http://developer.postgresql.org/docs/postgres/kernel-resources.html
2.1.2 Память для сортировки результата запроса: sort_mem
Этот параметр определяет объём памяти, которую процесс может использовать для сортировки результата запроса. Учтите, что такой объём может быть использован каждым процессом для каждой сортировки (в сложных запросах их может быть несколько).
Если объём памяти недостаточен для сортироки некоторого результата, то серверный процесс будет использовать временные файлы. Если же объём памяти слишком велик, то это может привести к своппингу.
Объём памяти задаётся параметром sort_mem в файле postgresql.conf. Единица измерения параметра -- 1 кБ. Значение по умолчанию -- 1024.
В качестве начального значения для параметра можете взять 2-4% доступной памяти.
Этот параметр может также быть задан для отдельного соединения. Если вы знаете, что в конкретном соединении будет выполняться запрос, требующий сортировки значительного объёма данных, то можете поднять значение sort_mem перед выполнением запроса.
2.1.3 Память для работы команды VACUUM: vacuum_mem
Этот параметр задаёт объём памяти, используемый командой VACUUM. Обычно эта команда больше нагружает диски, но увеличение vacuum_mem позволит ускорить процесс за счёт хранения в памяти больших объёмов информации об удалённых записях.
Объём памяти задаётся параметром vacuum_mem в файле postgresql.conf. Единица измерения параметра -- 1 кБ. Значение по умолчанию -- 8192.
Этот параметр может также быть задан для отдельного соединения. Можете сделать его поменьше для частых регулярных запусков VACUUM и большим для ежедневных/еженедельных запусков VACUUM FULL.
2.2 Журнал транзакций и контрольные точки
Журнал транзакций PostgreSQL работает следующим образом: все изменения в файлах данных (в которых находятся таблицы и индексы) производятся только после того, как они были занесены в журнал транзакций, при этом записи в журнале должны быть гарантированно записаны на диск.
В этом случае нет необходимости сбрасывать на диск изменения данных при каждом успешном завершении транзакции: в случае сбоя БД может быть восстановлена по записям в журнале. Таким образом, данные из буферов сбрасываются на диск при проходе контрольной точки: либо при заполнении нескольких (параметр checkpoint_segments, по умолчанию 3) сегментов журнала транзакций, либо через определённый интервал времени (параметр checkpoint_timeout, измеряется в секундах, по умолчанию 300).
Изменение этих параметров прямо не повлияет на скорость чтения, но может принести большую пользу, если данные в базе активно изменяются.
2.2.1 fsync и стоит ли его трогать
Наиболее радикальное из возможных решений -- выставить значение No параметру fsync. При этом записи в журнале транзакций не будут принудительно сбрасываться на диск, что даст большой прирост скорости записи. Учтите: вы жертвуете надёжностью, в случае сбоя целостность базы будет нарушена, и её придётся восстанавливать из резервной копии!
Использовать этот параметр рекомендуется лишь в том случае, если вы всецело доверяете своему «железу» и своему источнику бесперебойного питания. Ну или если данные в базе не представляют для вас особой ценности...
В пункте 2.5.1 описано менее радикальное решение, позволяющее, тем не менее, добиться хорошего прироста производительности.
2.2.2 Уменьшение количества контрольных точек
Если в базу заносятся большие объёмы данных, то контрольные точки могут происходить слишком часто2. При этом производительность упадёт из-за постоянного сбрасывания на диск данных из буфера.
Для увеличения интервала между контрольными точками нужно увеличить количество сегментов журнала транзакций (checkpoint_segments). Каждый сегмент занимает 16 МБ, так что на диске будет занято дополнительное место. Обычно на диске будет не менее одного и не более 2*checkpoint_segments+1 сегментов журнала.
Следует также отметить, что чем больше интервал между контрольными точками, тем дольше будут восстанавливаться данные по журналу транзакций после сбоя.
2.2.3 Прочие параметры
- wal_sync_method
- определяет метод, при помощи которого записи в журнале транзакций принудительно сбрасываются на диск. Значение по умолчанию зависит от платформы. Возможно, изменение этого параметра позволит увеличить производительность (а возможно, и не позволит).
- wal_buffers
- (в блоках по 8 кБ, 8 по умолчанию) определяет размер буфера журнала транзакций3, в котором накапливаются записи перед сбросом их на диск. Стоит увеличить буфер до 256-512 кБ, что позволит лучше работать с большими транзакциями.
- commit_delay
- (в микросекундах, 0 по умолчанию) и
- commit_siblings
- (5 по умолчанию) определяют задержку между попаданием записи в буфер журнала транзакций и сбросом её на диск. Если при успешном завершении транзакции активно не менее commit_siblings транзакций, то запись будет задержана на время commit_delay. Если за это время завершится другая транзакция, то их изменения будут сброшены на диск вместе, при помощи одного системного вызова. Эти параметры позволят ускорить работу, если параллельно выполняется много «мелких» транзакций.
2.3 Free Space Map: как избавиться от VACUUM FULL
Особенностями версионных движков БД (к которым относится и используемый в PostgreSQL) является следующее:
- Транзакции, изменяющие данные в таблице, не блокируют транзакции, читающие из неё данные, и наоборот (это хорошо);
- При изменении данных в таблице (командами UPDATE или DELETE) накапливается мусор4 (а это плохо).
До версии 7.2 команда VACUUM полностью блокировала таблицу. Начиная с версии 7.2, команда VACUUM накладывает более слабую блокировку, позволяющую параллельно выполнять команды SELECT, INSERT, UPDATE и DELETE над обрабатываемой таблицей. Старый вариант команды называется теперь VACUUM FULL.
Новый вариант команды не пытается удалить все старые версии записей и, соответственно, уменьшить размер файла, содержащего таблицу, а лишь помечает занимаемое ими место как свободное. Для информации о свободном месте есть следующие настройки:
- max_fsm_relations
- максимальное количество таблиц, для которых будет отслеживаться свободное место.
- max_fsm_pages
- количество блоков, для которых будет хранится информация о свободном месте. Информация хранится в разделяемой памяти, для каждой записи требуется по 6 байт.
Параметр max_fsm_relations должен быть не меньше общего количества таблиц во всех базах данной установки. В качестве начального приближения для max_fsm_pages можно взять половину от среднего количества записей, изменяемых (UPDATE или DELETE) между запусками команды VACUUM.
2.4 Прочие настройки
2.4.1 Оценка объёма кэша ОС: effective_cache_size
Этот параметр сообщает PostgreSQL примерный объём файлового кэша операционной системы, оптимизатор использует эту оценку для построения плана запроса.
Объём задаётся параметром effective_cache_size в postgresql.conf. Единица измерения -- блоки величиной 8 кБ. По умолчанию значение параметра составляет 1000.
Пусть в вашем компьютере 1,5 ГБ памяти, параметр shared_buffers установлен в 32 МБ, а параметр effective_cache_size в 800 МБ. Если запросу нужно 700 МБ данных, то PostgreSQL оценит, что все нужные данные уже есть в памяти и выберет более агрессивный план с использованием индексов и merge joins. Но если effective_cache_size будет всего 200 МБ, то оптимизатор вполне может выбрать более эффективный для дисковой системы план, включающий полный просмотр таблицы.
В качестве начального значения можете использовать 25-50% доступной5 памяти.
2.4.2 Сбор статистики
- default_statistics_target
- задаёт объём по умолчанию статистики, собираемой командой ANALYZE (см. пункт 3.1.2). Увеличение параметра заставит эту команду работать дольше, но может позволить оптимизатору строить более быстрые планы, используя полученные дополнительные данные. Объём статистики для конкретного поля может быть задан командой ALTER TABLE ... SET STATISTICS.
- stats_start_collector
- включать ли сбор статистики. По умолчанию включён, отключайте, только если статистика вас совершенно не интересует.
- stats_reset_on_server_start
- обнулять ли статистику при перезапуске сервера. По умолчанию -- обнулять.
- stats_command_string
- передавать ли сборщику статистики информацию о текущей выполняемой команде и времени начала её выполнения. По умолчанию эта возможность отключена. Следует отметить, что эта информация будет доступна только привилегированным пользователям и пользователям, от лица которых запущены команды, так что проблем с безопасностью быть не должно.
- stats_row_level, stats_block_level
- собирать ли информацию об активности на уровне записей и блоков соответственно. По умолчанию сбор отключён.
2.5 Диски и файловые системы
Очевидно, что от качественной дисковой подсистемы в сервере БД зависит немалая часть производительности. Вопросы выбора и тонкой настройки «железа», впрочем, не являются темой данной статьи, ограничимся уровнем файловой системы.
Единого мнения насчёт наиболее подходящей для PostgreSQL файловой системы нет, поэтому рекомендуется использовать ту, которая лучше всего поддерживается вашей операционной системой. При этом учтите, что современные журналирующие файловые системы не намного медленнее не-журналирующих, а выигрыш -- быстрое восстановление после сбоев -- от их использования велик.
Вы легко можете получить выигрыш в производительности без побочных эффектов, если примонтируете файловую систему, содержащую базу данных, с параметром noatime6.
2.5.1 Перенос журнала транзакций на отдельный диск
При доступе к диску изрядное время занимает не только собственно чтение данных, но и перемещение магнитной головки.
Если в вашем сервере есть несколько физических дисков7, то вы можете разнести файлы базы данных и журнал транзакций по разным дискам. Данные в сегменты журнала пишутся последовательно, более того, записи в журнале транзакций сразу сбрасываются на диск, поэтому в случае нахождения его на отдельном диске магнитная головка не будет лишний раз двигаться, что позволит ускорить запись.
Порядок действий:
- Остановите сервер (!).
- Перенесите каталог pg_xlog, находящийся в каталоге с базами данных, на другой диск.
- Создайте на старом месте символическую ссылку.
- Запустите сервер.
Footnotes
- ... 641
- актуально для версий до 7.4
- ...2
- «слишком часто» можно определить как «чаще раза в минуту». Вы также можете задать параметр checkpoint_warning (в секундах): в журнал сервера будут писаться предупреждения, если контрольные точки происходят чаще заданного.
- ...3
- буфер находится в разделяемой памяти и является общим для всех процессов
- ...4
- под которым понимаются старые версии изменённых/удалённых записей
- ...5
- т.е. не занятой операционной системой и приложениями
- ...noatime6
- при этом не будет отслеживаться время последнего доступа к файлу
- ...7
- несколько логических разделов на одном диске здесь, очевидно, не помогут: головка всё равно будет одна
Next: 3 Оптимизация БД и Up: PostgreSQL: настройка производительности Previous: 1 Введение