postgresql数据库|pgbouncer连接池压测和直连postgresql数据库压测对比

一、

压测目的

相信很多同学对于连接池技术还是比较感兴趣的,但对于pgbouncer是否能够承担起连接池的重任,可能很多同学都有点持怀疑的态度。

那么,本文以centos7,采用pgbench内置压测工具,通过两种连接方式来进行数据库压测,以得出pgbouncer哪些参数会影响连接池的性能;连接池和直连数据库到底哪个孰优孰劣,每一种连接压测后的tps详解。

二、

实验环境介绍

本次压测实验采用VMware虚拟机,虚拟机安装的操作系统是centos7,postgresql数据库的版本是12.4,两种压测都是远程连接,也就是说一种压测是通过数据库原生端口开始,一种压测是通过pgbouncer的端口开始。pgbouncer的版本是最新版本的1.5.1

bash 复制代码
[root@centos1 ~]# su - postgres
Last login: Thu Jan 29 20:22:42 CST 2026 on pts/4
-bash-4.2$ psql -p 6432 -d pgbouncer -U postgres
Password for user postgres: 
psql (12.4, server 1.25.1/bouncer)
Type "help" for help.

硬件方面,cpu是16核心,内存是8G,pgbouncer开放的端口是6432,数据库开放的端口是15433

bash 复制代码
[root@centos1 ~]# netstat -antup |grep 15433
tcp        0      0 0.0.0.0:15433           0.0.0.0:*               LISTEN      1334/postmaster     
tcp6       0      0 :::15433                :::*                    LISTEN      1334/postmaster     
[root@centos1 ~]# netstat -antup |grep 6432
tcp        0      0 0.0.0.0:6432            0.0.0.0:*               LISTEN      1300/pgbouncer      
tcp6       0      0 :::6432                 :::*                    LISTEN      1300/pgbouncer 
[root@centos1 ~]# free -mh
              total        used        free      shared  buff/cache   available
Mem:           7.6G        217M        6.6G        309M        798M        6.9G
Swap:            0B          0B          0B

软件方面,pgbouncer配置的主要参数如下:

bash 复制代码
client_idle_timeout = 600
idle_transaction_timeout = 300
server_lifetime = 600
server_idle_timeout = 399
max_db_connections = 800
reserve_pool_timeout = 1
reserve_pool_size = 200
default_pool_size = 400
max_client_conn = 2000
server_check_delay = 10
server_check_query = select 1
max_prepared_statements = 599
pool_mode = transaction

数据库方面所有参数都是原始默认参数,除了端口修改为了15433,连接数修改为了5000

三、

pgbench的安装部署

生成一个2000W条的大表,然后对该表做查询,写入的测试,从而得出数据库的性能和并发指标,下面是大表的创建代码:

随机数函数:

bash 复制代码
create or replace function gen_id(  
 a date,  
 b date  
)   
returns text as $$  
select lpad((random()*99)::int::text, 3, '0') ||   
    lpad((random()*99)::int::text, 3, '0') ||   
    lpad((random()*99)::int::text, 3, '0') ||   
    to_char(a + (random()*(b-a))::int, 'yyyymmdd') ||   
    lpad((random()*99)::int::text, 3, '0') ||   
    random()::int ||   
    (case when random()*10 >9 then 'xy' else (random()*9)::int::text end ) ;  
$$ language sql strict;

创建测试表结构:

bash 复制代码
CREATE SEQUENCE test START 1;
create table if not exists testpg (
	"id" int8 not null DEFAULT nextval('test'::regclass),
	CONSTRAINT "user_vendorcode_pkey" PRIMARY KEY ("id"),
	"suijishuzi" VARCHAR ( 255 ) COLLATE "pg_catalog"."default"
);

插入2000W条数据,根据机器性能,大概5到10分钟左右:

bash 复制代码
insert into testpg SELECT generate_series(1,20000000) as xm, gen_id('1949-01-01', '2023-10-16') as num;

随机更新字段suijishuzi:

bash 复制代码
-- 文件名:update_test.sql
BEGIN;
 
-- 生成随机数(1~100)决定更新范围
\set update_range random(1, 100)
 
-- 随机选择要更新的 ID(确保 ID 存在)
\set target_id random(1, :scale)
 
-- 执行更新操作
UPDATE testpg
SET suijishuzi = md5(random()::text)  -- 生成随机字符串作为新值
WHERE id = :target_id;
 
COMMIT;

创建数据库pgbench,并生成pgbench的内置表:

bash 复制代码
create database pgbench;
pgbench -U postgres -i pgbench

以上表准备完毕后,就可以开始正式压测了,压测主要是使用 update_test.sql这个SQL脚本,模拟高并发下的更新性能,每次压测完毕后,等待五分钟以让top命令恢复正常状态,并尽量去掉缓存的影响

四、

正式压测记录

第一组,pgbouncer连接池

预编译模式,400个数据库连接数,15个进程,压测时间30秒

bash 复制代码
pgbench  -M prepared -v -r -P 1 -f  ./update_test.sql -c 400 -j 15 -T 30 -D scale=20000000 -Upostgres -d postgres1 -P 5 -h 192.168.123.100 -p6432

cpu使用率在百分之十左右,内存使用1G左右,压测报告如下:

bash 复制代码
transaction type: ./update_test.sql
scaling factor: 1
query mode: prepared
number of clients: 400
number of threads: 15
duration: 30 s
number of transactions actually processed: 112967
latency average = 103.640 ms
latency stddev = 67.994 ms
tps = 3751.554637 (including connections establishing)
tps = 3751.934390 (excluding connections establishing)
statement latencies in milliseconds:
        27.082  BEGIN;
         0.168  \set update_range random(1, 100)
         0.122  \set target_id random(1, :scale)
        34.674  UPDATE testpg
        41.599  COMMIT;

第二组,pgbouncer连接池

预编译模式,400个数据库连接数,15个进程,压测时间300秒,和第一组间隔3分钟

bash 复制代码
pgbench  -M prepared -v -r -P 1 -f  ./update_test.sql -c 400 -j 15 -T 300 -D scale=20000000 -Upostgres -d postgres1 -P 5 -h 192.168.123.100 -p6432

cpu使用率为百分之十三,截图截稍晚了

压测报告如下:

bash 复制代码
transaction type: ./update_test.sql
scaling factor: 1
query mode: prepared
number of clients: 400
number of threads: 15
duration: 300 s
number of transactions actually processed: 1606670
latency average = 73.662 ms
latency stddev = 44.483 ms
tps = 5355.159074 (including connections establishing)
tps = 5355.321370 (excluding connections establishing)
statement latencies in milliseconds:
        19.377  BEGIN;
         0.141  \set update_range random(1, 100)
         0.115  \set target_id random(1, :scale)
        26.258  UPDATE testpg
        27.769  COMMIT;

以这两组压测对比,可以看到第二次压测明显tps升高了,那么,原因是什么呢?

推测是pgbouncer连接池发挥作用了,在第一次压测时,创建了大量的连接,导致tps下降,第二次压测直接拿第一次创建的连接复用,因此,tps大幅度提升;其次是update阶段和commit阶段,也有百分之三十左右的提升。

第三组。数据库直连

和第二组间隔三分钟,预编译模式,400个数据库连接数,15个进程,压测时间30秒,压测报告如下:

bash 复制代码
transaction type: ./update_test.sql
scaling factor: 1
query mode: prepared
number of clients: 400
number of threads: 15
duration: 30 s
number of transactions actually processed: 127742
latency average = 78.970 ms
latency stddev = 75.434 ms
tps = 4227.694815 (including connections establishing)
tps = 4233.449310 (excluding connections establishing)
statement latencies in milliseconds:
        15.675  BEGIN;
         0.756  \set update_range random(1, 100)
         0.236  \set target_id random(1, :scale)
        23.724  UPDATE testpg
        38.572  COMMIT;

cpu使用率最高到百分之二十多一点,内存使用1G左右

第四组,数据库直连

和第三组间隔三分钟,预编译模式,400个数据库连接数,15个进程,压测时间300秒,压测报告如下:

bash 复制代码
transaction type: ./update_test.sql
scaling factor: 1
query mode: prepared
number of clients: 400
number of threads: 15
duration: 300 s
number of transactions actually processed: 1536284
latency average = 67.016 ms
latency stddev = 73.166 ms
tps = 5108.252035 (including connections establishing)
tps = 5108.422198 (excluding connections establishing)
statement latencies in milliseconds:
        13.348  BEGIN;
         0.652  \set update_range random(1, 100)
         0.202  \set target_id random(1, :scale)
        18.535  UPDATE testpg
        34.278  COMMIT;

可以看到,直连数据库的性能和pgbouncer连接池的性能接近,但资源消耗完全和连接池无法相比,最高cpu使用达到了百分之三十五,并且idle进程大起大落的很厉害,内存使用方面两者基本一致,都是1G左右

第五组,数据库直连

和第四组间隔10来分钟,直接运行模式,400个数据库连接数,15个进程,压测时间300秒,压测报告如下:

bash 复制代码
transaction type: ./update_test.sql
scaling factor: 1
query mode: simple
number of clients: 400
number of threads: 15
duration: 300 s
number of transactions actually processed: 1440749
latency average = 71.457 ms
latency stddev = 69.900 ms
tps = 4796.305166 (including connections establishing)
tps = 4796.657038 (excluding connections establishing)
statement latencies in milliseconds:
        14.275  BEGIN;
         0.695  \set update_range random(1, 100)
         0.209  \set target_id random(1, :scale)
        19.858  UPDATE testpg
        36.417  COMMIT;

最高cpu使用率百分之三十五左右,内存仍然是使用1G左右,没有太大变化

第六组,pgbouncer连接池

和第五组间隔10来分钟,直接运行模式,400个数据库连接数,15个进程,压测时间300秒,压测报告如下:

bash 复制代码
transaction type: ./update_test.sql
scaling factor: 1
query mode: simple
number of clients: 400
number of threads: 15
duration: 300 s
number of transactions actually processed: 1335101
latency average = 88.733 ms
latency stddev = 55.627 ms
tps = 4448.145554 (including connections establishing)
tps = 4448.234075 (excluding connections establishing)
statement latencies in milliseconds:
        23.778  BEGIN;
         0.200  \set update_range random(1, 100)
         0.152  \set target_id random(1, :scale)
        30.420  UPDATE testpg
        34.184  COMMIT;

最高cpu使用率百分之三十左右,内存仍然是使用1G左右,没有太大变化,第五组和第六组相比,tps性能基本一样,资源使用率cpu方面连接池稍显优势,内存方面两者基本相同。

压测总结:

从这几次压测来看,可以得出一个比较准确的高并发下的postgresql数据库性能,即pgbouncer连接池基本等于数据库直连,但,数据库服务器资源使用明显pgbouncer连接池更低,有数据库连接池的情况要比直连数据库低一半左右的资源使用。 server_check_delay = 10是一个比较安全可靠的连接检测参数,如果设置为默认30,连接池的性能会下降比较多,稍微有点明显,在本次压测中并没有展示此参数,以后补充。

未完待续!!!!!

相关推荐
m0_686041612 小时前
Python类型提示(Type Hints)详解
jvm·数据库·python
2601_949593652 小时前
基础入门 React Native 鸿蒙跨平台开发:FlatList 性能优化
react native·性能优化·harmonyos
三水不滴2 小时前
Redis 持久化机制
数据库·经验分享·redis·笔记·缓存·性能优化
lusasky2 小时前
Claude Code v2.1.0+ 版本集成LSP
大数据·数据库·人工智能
凯子坚持 c3 小时前
Qt常用控件指南(7)
服务器·数据库·qt
diediedei3 小时前
Python字典与集合:高效数据管理的艺术
jvm·数据库·python
气可鼓不可泄3 小时前
将dmpython 封装在容器镜像里
数据库·python
m0_561359673 小时前
超越Python:下一步该学什么编程语言?
jvm·数据库·python
mango_mangojuice3 小时前
Linux学习笔记 1.19
linux·服务器·数据库·笔记·学习