Простаивающие процессы postgres занимают много памяти


Я пытаюсь понять, почему ~30 незанятых процессов postgres занимают так много памяти для конкретных процессов после нормального использования. Я использую Postgres 9.3.1 и CentOS release 6.3 (Final). Используя top, я вижу, что многие соединения postgres используют до 300 МБ (в среднем ~200 Мб) неразделяемой (RES-SHR) памяти:

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 3534 postgres  20   0 2330m 1.4g 1.1g S  0.0 20.4   1:06.99 postgres: deploy mtalcott 10.222.154.172(53495) idle
 9143 postgres  20   0 2221m 1.1g 983m S  0.0 16.9   0:14.75 postgres: deploy mtalcott 10.222.154.167(35811) idle
 6026 postgres  20   0 2341m 1.1g 864m S  0.0 16.4   0:46.56 postgres: deploy mtalcott 10.222.154.167(37110) idle
18538 postgres  20   0 2327m 1.1g 865m S  0.0 16.1   2:06.59 postgres: deploy mtalcott 10.222.154.172(47796) idle
 1575 postgres  20   0 2358m 1.1g 858m S  0.0 15.9   1:41.76 postgres: deploy mtalcott 10.222.154.172(52560) idle

Всего насчитывается около 29 неработающих соединений. Эти простаивающие соединения продолжают расти в памяти до тех пор, пока машина не начнет использовать swap, а затем производительность снизится до остановка. Как и ожидалось, сброс соединения очищает память конкретного процесса. То же самое количество соединений на той же машине использует только 20% памяти (с 0 swap) при периодическом повторном подключении. За какую информацию держатся эти процессы? Я ожидал бы, что длительно работающие, простаивающие процессы postgres будут иметь такое же использование памяти, как и совершенно новые, простаивающие процессы.

Стоит отметить: я активно использую схемы. При каждом запросе к моему приложению я устанавливаю и сбрасываю search_path.

1 19

1 ответ:

Какую информацию удерживают эти процессы? Я ожидал бы, что длительно работающие, простаивающие процессы postgres будут иметь такое же использование памяти, как и совершенно новые, простаивающие процессы.

На самом деле есть довольно много вещей, которые Postgres будет кэшировать в локальной памяти, как только он загрузил их:

  • relcache (relation descriptors)
  • catcache (записи системного каталога)
  • скомпилированные деревья для функций plpgsql

Для большинства вариантов использования все они добавляют вплоть до ничтожной суммы. Ключевым моментом здесь было интенсивное использование схем и влияние на релкеш. Эта база данных содержит ~500 схем, каждая с теми же ~ 90 таблицами. Для Postgres, несмотря на то, что все схемы одинаковы, это работает до 45 000 таблиц (500*90).

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

Возможные решения:

  • повторное соединение после определенного количества запросов
  • добавить больше памяти
  • объединение соединений, чтобы установить потолок на число соединений postgres, используя pgpool-II или PgBouncer

Спасибо тому лейну и Мерлину Монкуру за помощь в этом по спискам рассылкиPostgres .