背景

常用数据库的基准测试最关键的衡量指标有:吞吐量(Throughput)、响应时间(RT)或延迟(Latency)和并发量。
吞吐量是衡量数据库的单位时间内的事务处理能力,常用的单位是TPS(每秒事务数)。
响应时间或延迟,描述操作过程里用来响应服务的时间,根据不同的应用可以使用分钟、秒、毫秒、微秒作为单位。通常还会根据响应时间的最大值、最小值以及平均值做分组统计,例如90%的运行周期内的响应时间是1毫秒,10%的运行周期内的响应时间是5毫秒,这样可以得出相对客观的测试结果。
并发量是指同时工作的连接数。
在不同的测试场景,需要关注的指标也会不同,分析测试结果时,吞吐量、响应时间、并发量是必须关注的三个基本要素。


pgbench介绍
pgbench是一个基准测试工具,可以执行内置的测试脚本,也可以自定义脚本文件。pgbench运行结束后,会输出一份测试结果的报告:
transaction type行记录本次测试所使用的测试类型;
scaling factor记录pgbench在初始化时设置的数据量的比例因子;
query mode是测试时指定的查询类型,包括simple查询协议、extended查询协议或prepared查询协议;
number of clients是测试时指定的客户端数量;
number of threads是测试时指定的每个客户端的线程数;
number of transactions per client是测试时指定的每个客户端运行的事务数;
number of transaction actually processed是测试结束时实际完成的事务数和计划完成的事务数,实际完成的事务数应该和计划完成的事务数相等,如果有事务执行失败,则只会显示实际完成的事务数;
latency average是测试过程中的平均响应时间;
tps=(including connections establishing和excluding connections establishing)值分别是包含和不包含建立连接开销的TPS值。


pgbench使用
1,初始化数据
pgbench内嵌脚本需要4张表:pgbench_branches、pgbench_tellers、pgbench_accounts和pgbench_history。
使用pgbench初始化测试数据,pgbench会自动去创建这些表并生成测试数据。在初始化过程中,如果数据库中存在和这些表同名的数据,pgbench会删除这些表重新进行初始化。
pgbench初始化测试数据的命令如下所示:

[postgres@00353374b53f ~]$ pgbench -i -s 2 -F 80 -h 127.0.0.1 -p 5433 -U postgres -d postgrescreating tables...100000 of 200000 tuples (50%) done (elapsed 0.03 s, remaining 0.03 s)200000 of 200000 tuples (100%) done (elapsed 0.06 s, remaining 0.00 s)vacuum...set primary keys...done.

2,内置脚本测试

pgbench的内置脚本有tcp-like、tcp-update和select-only三种。可以通过以下命令查看当前版本的pgbench包含哪些集成的测试脚本。

[postgres@00353374b53f ~]$ pgbench -b listAvailable builtin scripts: tpcb-like simple-update select-only

tpcb-like执行的脚本是一个包含SELECT、UPDATE、INSERT的事务:
simple-update执行的脚本如下:
select-only执行的脚本如下:
可以使用下列参数设置内置脚本测试的方式:
-b, --builtin=NAME[@W]
NAME参数指定使用哪一种脚本进行测试,默认使用tpcb-like这一种测试脚本。
例如使用simple-update进行测试,代码如下所示:

[postgres@00353374b53f ~]$ pgbench -b simple-update -h 127.0.0.1 -p 5433 -U postgres postgresstarting vacuum...end.transaction type: <builtin: simple update>scaling factor: 2query mode: simplenumber of clients: 1number of threads: 1number of transactions per client: 10number of transactions actually processed: 10/10latency average = 3.172 mstps = 315.248574 (including connections establishing)tps = 344.186687 (excluding connections establishing)

还可以使用3种内置脚本进行混合测试,并在脚本名称后面加上@符号,@符号后面加上一个脚本运行比例的权重的整数值,例如使用simple-update和select-only两种内置脚本,并且以2:8的比例混合进行测试,代码如下所示:

[postgres@00353374b53f ~]$ pgbench -b simple-update@8 -b select-only@2 -h 127.0.0.1 -p 5433 -U postgres postgresstarting vacuum...end.transaction type: multiple scriptsscaling factor: 2query mode: simplenumber of clients: 1number of threads: 1number of transactions per client: 10number of transactions actually processed: 10/10latency average = 1.104 mstps = 905.469033 (including connections establishing)tps = 1228.954160 (excluding connections establishing)SQL script 1: <builtin: simple update> - weight: 8 (targets 80.0% of total) - 7 transactions (70.0% of total, tps = 633.828323) - latency average = 1.071 ms - latency stddev = 0.530 msSQL script 2: <builtin: select only> - weight: 2 (targets 20.0% of total) - 3 transactions (30.0% of total, tps = 271.640710) - latency average = 0.197 ms - latency stddev = 0.004 ms

使用内置脚本混合测试,最终输出的结果除了常规的报告项之外,还会输出每个测试脚本的实际占比,以及每个类型的平均延时、TPS等等更加详细的值。使用混合方式的测试,可以方便模拟不同的读写比。

3,自定义测试
pgbench支持从一个文件中读取事务脚本来替换默认的事务脚本,达到运行自定义测试场景的目的。
1)创建测试表:

postgres=# create table tb1(id serial primary key,ival int);CREATE TABLE

2)运行自定义脚本
在pgbench命令中使用-f参数运行自定义的脚本,举例如下:

echo "select id,ival from tbl order by id desc limit 10;" > bench_script_for_select.sql[postgres@00353374b53f ~]$ pgbench -f bench_script_for_select.sql -h 127.0.0.1 -p 5433 -U postgres postgresstarting vacuum...end.transaction type: bench_script_for_select.sqlscaling factor: 1query mode: simplenumber of clients: 1number of threads: 1number of transactions per client: 10number of transactions actually processed: 10/10latency average = 0.557 mstps = 1794.043775 (including connections establishing)tps = 3725.782414 (excluding connections establishing)

在测试过程中,通常会使用变量作为SQL语句的参数传入。在脚本中可以使用类似于psql的以反斜杠开头的元命令和内建函数定义变量。pgbench自定义脚本支持的元命令有:
\sleep number[us|ms|s]:每执行一个事物暂停一定时间,但是可以是微秒、毫秒和秒,如果不写单位,默认使用秒。
\set varname expression:用于设置一个变量、元命令、参数和参数的值之间用空格分开。在pgbench中定义了一些可以在元命令中使用的函数,例如random(int,int)。
例如自定义一个脚本,在tb1表的ival字段中插入一个随机数,代码如下所示:

[postgres@00353374b53f ~]$ cat bench_script_for_insert.sql\sleep 500ms\set ival random(1,100000)INSERT INTO tb1(ival) VALUES(:ival)

运行pgbench使用该脚本进行测试,如下所示:

[postgres@00353374b53f ~]$ pgbench -f bench_script_for_insert.sql -h 127.0.0.1 -p 5433 -U postgres postgresstarting vacuum...end.transaction type: bench_script_for_insert.sqlscaling factor: 1query mode: simplenumber of clients: 1number of threads: 1number of transactions per client: 10number of transactions actually processed: 10/10latency average = 501.557 mstps = 1.993791 (including connections establishing)tps = 1.994899 (excluding connections establishing)

检查测试表,结果如下:

postgres=# select count(id) from tb1; count------- 10(1 row)postgres=# select * from tb1 order by id desc limit 3; id | ival----+------- 10 | 12642 9 | 79033 8 | 50844(3 rows)

可以看到INSERT成功地插入了预期的值,共10条记录。从pgbench输出的测试报告看,平均延迟(latency average)等于500多毫秒,成功执行了10个事务。

和使用内置脚本一样,可以在-f的参数后加上@符号再加上权重,以不同比例运行多个自定义脚本。全种子并不是一个百分比的值,而是相对一个固定的数值,例如第一个脚本运行3次,第二个脚本运行10次,下面是一个在多个测试脚本中加入权重值选项进行测试的例子:

4,其它选项

1)模拟客户端数量和连接方式
-c 指定模拟客户端的数量,也就是并发数据库的连接数量,默认为1.
-C 指定是否为每个事物创建一个新的连接,如果每次都创建新的连接则性能会明显下降很多,测试连接池性能时这个参数比较有用。
-j 在多线程CPU上进行测试,将模拟的客户端平均分配在各个线程上。
2)单次测试的运行时间(下面只能二选一)
-T seconds或--time=seconds参数用来设置测试的秒数;例如需要测试1小时,在测试命令中增加参数-T 3600即可。
-t transactions或--transactions=transactions参数指定每个客户端运行多少个固定数量的事务就结束本地测试,默认为10个。
3)用gudingsulv运行测试脚本
使用-R可以用固定速率执行事务,单位是TPS。如果给定的既定速率的值大于最大可能的速率,则该速率限制不会影响结果。
4)超出阈值的事务的报告
使用-L参数设置一个阈值,对超过这个阈值的事务进行独立报告和计数,单位是毫秒。
5)输出选项
pgbench又丰富的测试结果报告的输出格式。
-d 可以输出debug信息,通常不使用它。
-P 可以每隔一段时间输出一次测试结果。
-l或--log将每一个事物执行的时间计入一个名称为“pgbench_log.n”的日志文件中,如果使用-j参数指定使用多个线程,则会生成名称为“pgbench_log.n.m”的日志文件。其中n是测试时pgbench的PID,m是从1开始的线程的序号,pgbench_log是默认的日志文件的前缀,例如:

[postgres@00353374b53f ~]$ pgbench -T 10 -l -c 6 -j 2 -f bench_script_for_select.sql@3 -f bench_script_for_insert.sql@10 -h 127.0.0.1 -p 5433 -U postgres postgres starting vacuum...end.transaction type: multiple scriptsscaling factor: 1query mode: simplenumber of clients: 6number of threads: 2duration: 10 snumber of transactions actually processed: 164latency average = 367.479 mstps = 16.327451 (including connections establishing)tps = 16.336404 (excluding connections establishing)SQL script 1: bench_script_for_select.sql - weight: 3 (targets 23.1% of total) - 44 transactions (26.8% of total, tps = 4.380536) - latency average = 0.405 ms - latency stddev = 0.554 msSQL script 2: bench_script_for_insert.sql - weight: 10 (targets 76.9% of total) - 120 transactions (73.2% of total, tps = 11.946915) - latency average = 500.896 ms - latency stddev = 1.606 ms

测试结束后,在运行pgbench的目录会生成pgbench_log.293825和pgbench_log.293825.1两个日志文件。它们的内容格式如下:

[postgres@00353374b53f ~]$ cat pgbench_log.293825client_id transaction_no time script_no time_epoch time_us[schedule_lag]0 0 502229 1 1623307003 23531 0 503174 1 1623307003 32992 0 503260 1 1623307003 33852 1 770 0 1623307003 41572 2 305 0 1623307003 44650 1 500455 1 1623307003 5028481 1 500769 1 1623307003 5040711 2 716 0 1623307003 5047902 3 500681 1 1623307003 505148

其中client_no为客户端的序号id;transaction_no为事务的序号;time是该事务所花费的时间,单位为微秒;在使用了多个脚本时,script_no标识该事务使用的是哪个脚本;time_epoch/time_us是一个Unix纪元格式的时间戳以及一个显示事务完成时间的以微秒计的偏移量(适用于创建一个带有分数秒的ISO 8601时间戳)。

posted on 2021-07-11 10:19  jl1771  阅读(914)  评论(0编辑  收藏  举报