PostgreSQL использует большой объем памяти для постоянного подключения - PullRequest
2 голосов
/ 01 августа 2009

У меня есть приложение на C ++, использующее PostgreSQL 8.3 для Windows. Мы используем интерфейс libpq.

У нас есть многопоточное приложение, в котором каждый поток открывает соединение и продолжает использовать его без PQFinish.

Мы замечаем, что для каждого запроса (особенно для операторов SELECT) потребление памяти postgres.exe будет увеличиваться. Он поднимается до 1,3 ГБ. В конце концов, postgres.exe вылетает и вынуждает нашу программу создать новое соединение.

Кто-нибудь сталкивался с этой проблемой раньше?

РЕДАКТИРОВАТЬ: shared_buffer в настоящее время установлен в 128 МБ в нашей конфигурации. файл.

EDIT2: обходной путь, который мы сейчас используем, заключается в том, чтобы вызывать PQfinish для каждой транзакции. Но тогда это немного замедляет нашу обработку, поскольку установление соединения каждый раз происходит довольно медленно.

Ответы [ 3 ]

4 голосов
/ 18 апреля 2012

В PostgreSQL каждое соединение имеет выделенный бэкэнд. Этот бэкэнд не только содержит состояние соединения и сеанса, но также является механизмом выполнения. Бэкэнды не так уж и дешевы, чтобы их можно было лежать без дела, и они требуют затрат памяти и синхронизации даже в режиме ожидания.

Существует оптимальное количество активно работающих бэкэндов для любого данного сервера Pg в любой заданной рабочей нагрузке, где добавление большего количества рабочих бэкэндов замедляет работу, а не ускоряет ее. Вы хотите найти эту точку и ограничить количество бэкэндов до этого уровня. К сожалению, волшебного рецепта для этого нет, в основном это касается бенчмаркинга - на вашем оборудовании и с вашей рабочей нагрузкой.

Если вам нужно больше соединений, чем это, вы должны использовать прокси или систему пула, которая позволяет вам отделить «состояние соединения» от «механизма выполнения». Два популярных варианта: PgBouncer и PgPool-II . Вы можете поддерживать легкие соединения между вашим приложением и прокси / пулером и позволить ему планировать рабочую нагрузку, чтобы сервер базы данных работал с оптимальной нагрузкой. Если поступает слишком много запросов, некоторые ждут выполнения, вместо того чтобы конкурировать за ресурсы и замедлять все запросы на сервере.

См. postgresql wiki .

Обратите внимание, что если ваша рабочая нагрузка в основном для чтения, и особенно если в ней есть элементы, которые не часто меняются, для которых вы можете определить надежную схему аннулирования кэша , вы также можете потенциально использовать memcached или Redis уменьшить нагрузку на вашу базу данных. Это требует изменения приложения. LISTEN и NOTIFY в PostgreSQL помогут вам сделать нормальную аннулирование кэша.

Многие ядра СУБД имеют некоторое разделение механизма исполнения и состояния соединения, встроенного в структуру ядра СУБД. Sybase ASE, конечно, делает, и я думаю, что Oracle тоже, но я не слишком уверен в последнем. К сожалению, из-за модели PostgreSQL «один процесс на соединение» ему нелегко обойти работу между бэкэндами, что усложняет PostgreSQL эту задачу, поэтому большинство людей используют прокси или пул.

Я настоятельно рекомендую вам прочитать Высокая производительность PostgreSQL . У меня нет никаких связей или связей с Грегом Смитом или издателем *, я просто думаю, что это здорово и будет очень полезно, если вы беспокоитесь о производительности вашей БД.


* ... ну, я не знал, когда писал это. Сейчас я работаю в той же компании.

1 голос
/ 01 августа 2009

Использование памяти не обязательно является проблемой. PostgreSQL использует разделяемую память для некоторого кэширования, и эта память не учитывается в объеме используемой памяти процесса, пока она не будет фактически использована. Чем больше вы используете процесс, тем больше частей общих буферов будут активны в его адресном пространстве.

Если у вас есть большое значение для shared_buffers , это произойдет. Если оно слишком велико, процесс может выйти из адресного пространства и завершиться сбоем, да.

0 голосов
/ 09 апреля 2013

Проблема, вероятно, в том, что вы не закрываете транзакцию, В PostgreSQL, даже если вы выбираете только без DML, он выполняется в транзакции, которая требует отката. Добавление отката в конце транзакции уменьшит проблему с памятью

...