Помимо сохранения накладных расходов на подключение & отключите, если это делается по каждому запросу, пул соединений может направлять большое количество клиентских подключений вплоть до небольшого числа реальных подключений к базе данных. В PostgreSQL оптимальное количество активных соединений с базой данных обычно находится где-то вокруг ((2 * core_count) + effective_spindle_count). Выше этого числа ухудшаются как пропускная способность, так и латентность.
Иногда люди говорят: «Я хочу поддерживать 2000 пользователей с быстрым временем отклика». В значительной степени гарантировано, что если вы попытаетесь сделать это с 2000 действительными подключениями к базе данных, производительность будет ужасной. Если у вас есть машина с четырьмя четырехъядерными процессорами, и активный набор данных полностью кэширован, вы увидите гораздо лучшую производительность для этих пользователей 2000 путем перенаправления запросов через 35 подключений к базе данных.
Чтобы понять, почему это так, этот мысленный эксперимент должен помочь. Рассмотрим гипотетический сервер баз данных базы данных с одним ресурсом для совместного использования - одним ядром. Это ядро будет равномерно распределено между всеми параллельными запросами без накладных расходов. Предположим, что в тот же момент приходит все 100 запросов, каждый из которых нуждается в одной секунде процессорного времени. Ядро работает над всеми из них, сокращая время между ними, пока они не закончили через 100 секунд. Теперь рассмотрим, что произойдет, если вы поместите пул подключений на передней панели, который будет принимать 100 клиентских подключений, но одновременно будет делать только один запрос на сервер базы данных, помещая любые запросы, которые поступают, когда соединение занято в очередь. Теперь, когда 100 запросов поступают в одно и то же время, один клиент получает ответ за 1 секунду; другой получает ответ через 2 секунды, а последний клиент получает ответ через 100 секунд. Никто не должен был ждать дольше, чтобы получить ответ, пропускная способность такая же, но средняя задержка составляет 50,5 секунды, а не 100 секунд.
Реальный сервер базы данных имеет больше ресурсов, которые могут использоваться параллельно, но тот же принцип сохраняется, как только они насыщены, вы только повредите вещи, добавив больше параллельных запросов к базе данных. Это на самом деле хуже, чем пример, потому что с большим количеством задач у вас больше переключателей задач, повышенная конкуренция за блокировки и кеш, конфликты строк в кешках L2 и L3 и многие другие проблемы, которые сокращаются как пропускной способности, так и задержки. Кроме того, хотя высокий параметр work_mem
может помочь в запросе несколькими способами, этот параметр является пределом для каждого узла плана для каждого соединения, поэтому при большом количестве соединений вам нужно оставить это очень маленьким, чтобы избежать сброс кеша или даже ведение обмена, что приводит к более медленным планам или таким вещам, как хэш-таблицы, разливающиеся на диск.
Некоторые продукты базы данных эффективно создают пул соединений на сервере, но сообщество PostgreSQL заняло позицию, поскольку, поскольку лучший пул соединений делается ближе к клиентскому программному обеспечению, они оставляют его пользователям для управления этим. У большинства пулеметов есть какой-то способ ограничить соединения с базой данных с жестким числом, одновременно позволяя выполнять более параллельные запросы клиентов, чем это необходимо, ставя их в очередь. Это то, что вы хотите, и это должно быть сделано на транзакции , а не на заявление или соединение.
Существует также вероятность того, что ваша модель базы данных не соответствует запросам, которые вы стреляете в нее. Как правило, сетевые накладные расходы очень малы по сравнению с работой, необходимой для извлечения блоков данных с диска, а также: это не стоит производительности, а только задержки. (за исключением, возможно, для очень частого подключения/отключения) – wildplasser