Пул соединений pgx: настройка Max и Min
Пул соединений в pgx - это механизм предварительного создания и повторного использования подключений к базе данных. Вместо того чтобы открывать новое соединение на каждый запрос, вы берете готовое из пула, выполняете операцию и возвращаете его обратно. Это существенно снижает накладные расходы на установку TCP-соединения и аутентификацию.
Сколько нужно Max и Min соединений?
Однозначного ответа «для всех случаев» не существует. Оптимальные значения зависят от:
- Нагрузки на сервер БД - количество одновременных запросов;
- Времени выполнения запросов - долгие запросы занимают соединение дольше;
- Ресурсов PostgreSQL - каждое соединение потребляет память (обычно 2-10 МБ).
Начните с MinConns=2 и MaxConns=20. Для большинства веб-приложений этого достаточно. При росте нагрузки увеличивайте Max постепенно, следя за потреблением памяти на сервере БД.
Сколько весит одно соединение в pgx?
В среднем одно простаивающее соединение PostgreSQL занимает около 5-8 МБ оперативной памяти. Активное соединение при выполнении сложного запроса может потреблять больше. Для пула из 100 соединений это уже 500-800 МБ только на поддержание подключений. Учитывайте это при настройке MaxConns.
Аналогия с горутинами: есть ли «количество ядер» для pgx?
В отличие от горутин, где оптимальное число равно GOMAXPROCS, для пула соединений такого жёсткого лимита нет. Ключевой параметр - максимальное количество одновременных транзакций, которое выдерживает ваша база данных. Для pgx используйте MaxConns как верхнюю границу, ориентируясь на нагрузочное тестирование.
Практическое правило
Установите MaxConns равным 2 * (количество ядер CPU сервера БД). Это хорошая стартовая точка. Затем корректируйте под реальную нагрузку.
Самостоятельное управление соединением или делегирование пулу?
Всегда используйте встроенные методы пула: pool.Acquire() и conn.Release(). Это гарантирует, что соединение будет возвращено в пул даже при панике. Если вы вручную создаёте pgx.Conn, вы теряете преимущества пула - повторное использование и автоматическое восстановление после сбоев.
Пример корректного использования
conn, err := pool.Acquire(ctx)
if err != nil {
log.Fatal(err)
}
defer conn.Release()
row := conn.QueryRow(ctx, "SELECT id FROM users WHERE email=$1", email)
var id int
err = row.Scan(&id)Такой подход безопасен и эффективен.
Рекомендации по оптимизации пула
- Установите
MaxConnLifetime(например, 30 минут) для обновления старых соединений; - Используйте
MaxConnIdleTimeдля закрытия неактивных соединений при снижении нагрузки; - Мониторьте метрики:
pool.Stat().AcquiredConns()иpool.Stat().IdleConns().
Настройка пула - итеративный процесс. Начните с консервативных значений и увеличивайте их только при явной нехватке соединений.