Pgbench

From PostgreSQL 中文维基, PostgreSQL 中文站, PostgreSQL 中国社区, PostgreSQL Chinese community

Jump to: navigation, search

[编辑] pgbench

目录

pgbench 是一个简单的给 PostgreSQL 做性能测试的程序。它反复运行同样的 SQL 命令序列,可能是在多个并发数据库会话上头,然后检查平均的事务速度(每秒的事务数 tps)。缺省的时候,pgbench 测试一个(松散的)接近 TPC-B 的情况,每个事务包括五个 SELECT,UPDATE,和 INSERT命令。不过,我们可以很轻松地使用自己的事务脚本文件来实现其它情况。

典型的输出看上去会是这样:

transaction type: TPC-B (sort of)
scaling factor: 10
number of clients: 10
number of transactions per client: 1000
number of transactions actually processed: 10000/10000
tps = 85.184871 (including connections establishing)
tps = 85.296346 (excluding connections establishing)


头四航只是报告一些最重要的参数设置。跟着的一行报告完成的事务数和期望完成的事务数(后者只是客户端数乘以事务数);这两个会相等,除非在完成之前运行就失败了。最后两行报告 TPS 速率,分别有计算启动数据库会话时间和不计算启动会话时间的。

[编辑] 概述

缺省的 TPC-B 类的事务测试需要事先设定特定的表。要使用 pgbench 的 -i (初始化)选项来创建和填充这些表。(如果你测试的是客户自己的脚本,那就不需要这一步,但是你需要自己设置所需的环境)。初始化看上去像:

  pgbench -i [ other-options ] dbname


这里的 dbname 是一个已经创建的准备用来测试的数据库名称。(你可能还需要 -h,-p,和/或 -U 选项来声明如何连接到数据库服务器。)

注意:pgbench -i 创建四个表:accounts,branches,history 和 tellers,删除任何现有同名的表。如果你的数据库里有同名的表,要非常非常的小心!

缺省的“缩放因子(scale factor)”为 1 的时候,表初始化的行数为:

table           # of rows
-------------------------
branches        1
tellers         10
accounts        100000
history         0


你可以(而且,在大多数情况下,可能会)增加表中数据行的方法是使用 -s (缩放因子)选项。-F (填充因子 fillfactor)选项在这个时候也可以用。

一旦你完成了必要的步骤,就可以用不包括 -i 选项的命令来执行性能测试,也就是

 pgbench [ options ] dbname
  

几乎在所有场合下,你都需要一些选项来做有效的测试。最重要的选项是 -c(客户端数目),-t(事务的数目),和 -f (声明一个客户的脚本文件)。参阅下表获取完整的列表。

表 F-14 显示了在数据库初始化过程中使用的选项,表 F-15 显示了运行性能套件的时候的选项,表 F-16 显示了可用于两种场合的选项:

表 F-14. pgbench 初始化选项
选项 描述
-i 要求调用初始化模式。
-s scale_factor 生成的数据行放大 scale_factor 指定的倍数。比如 -s 100 讲隐含着账号表里有 10,000,000 行。缺省是 1。
-F fillfactor 用给出的 fillfactor 创建 accounts, tellers 和 branches 表缺省是 100。
表 F-15. pgbench 性能测试选项
选项 描述
-c clients 模拟的客户数,也就是并发数据库会话数目。缺省是 1。
-t transactions 每个客户端跑的事务数目。缺省是 10。
-N 不要更新 tellers 和 branches。这样会避免在这些表上的更新竞争,但是让测试案例更不像 TPC-B 了。
-S 执行纯 SELECT 的事务,而不是类 TPC-B 的测试。
-f filename 从 filename 中读取事务脚本。参阅下文获取细节。-N,-S,和 -f 是相互排斥的。
-n 在运行测试之前不执行 vacuum。如果你跑的是客户化的测试,不包括标准的 accounts,branches,history 和 tellers 表,那么这个选项就是必须的。
-v 在运行测试之前清理(vacuum)所有四个标准的表。如果不带 -n 也不带 -v,那么 pgbench 将清理 tellers 和 branches 表,并将删除 history 中的所有记录。
-D varname=value 定义一个客户端脚本使用的变量(见下文)。允许多个 -D 选项。
-C 为每个事务建立一个新连接,而不是每个客户端线程一个事务。这个有助于测量连接过荷。
-l 把每个事务花的时间写到 logfile。参阅下文获取细节。
-s scale_factor 在 pgbench 的输出汇报特定的缩放因子。对于内置的测试来说,这个是没必要的;正确的缩放因子可以通过计算 branches 表的行数得出。不过,在测试客户性能的时候(-f 选项),缩放因子就会报告为 1,除非使用了这个选项。
-d 打印调试输出。
表 F-16. pgbench 通常选项
选项 描述
-h hostname 数据库服务器的主机
-p port 数据库服务器的端口
-U login 连接的用户名

[编辑] pgbench 里实际执行的“事务”是什么?

缺省的事务脚本每个事务发出七个命令:

  1. BEGIN;
  2. UPDATE accounts SET abalance = abalance + :delta WHERE aid = :aid;
  3. SELECT abalance FROM accounts WHERE aid = :aid;
  4. UPDATE tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
  5. UPDATE branches SET bbalance = bbalance + :delta WHERE bid = :bid;
  6. INSERT INTO history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
  7. END;

如果你声明了 -N,那么第 4 和第 5 步并不包括在事务里。如果你声明了 -S,那么就只发出 SELECT。

[编辑] 客户脚本

pgbench 支持通过运行客户脚本测试客户化的性能情景,而不是缺省的事务脚本(上面描述的),方法是从一个文件读取脚本(-f 选项)。在这种场合下,一个“事务”的意思是该脚本文件的一次运行。你甚至可以声明多个脚本(多个 -f 选项),在这种场合下,每开始一个客户端会话就启动一个新的事务。

脚本文件的各是是每行一个 SQL 命令;不支持多行的 SQL 命令。空行和以 -- 开头的行被忽略。脚本文件的行也可以是“元命令”,它们是由 pgbench 自己解析的,如下所述。

脚本文件里有一个简单的变量替换极致。变量可以用命令行选项 -D 来设置,如上面解释的,或者用下面解释的元命令设置。除了用命令行参数 -D 设置的变量之外,变量 scale 预置成当前的缩放因子。在设置了变量之后,变量值就可以通过书写 :variablename 的方式插入到 SQL 命令中。在执行多个客户会话的时候,每个会话拥有自己的变量集。

脚本元命令用一个反斜杠开始(\)。原命令的参数是用空白分隔的。支持下列元命令:

\set varname operand1 [ operator operand2 ]

设置变量 varname 为一个计算出的整数值。每个操作数要么是一个整数常量,要么是一个具有整数值的 :variablename 引用。操作符可以是 +,-,*,或者 /。
例子:
   \set ntellers 10 * :scale
         

\setrandom varname min max

设置变量 varname 为一个范围是从 min 到 max 之间的随机整数值。每个限制可以是一个整数,也可以是一个具有整数值的 :variablename 引用。
例子:
   \setrandom aid 1 :naccounts
         

\sleep number [ us | ms | s ]

令脚本执行睡眠指定的微秒(us),毫秒(ms)或秒(s)数。如果省略单位,则缺省是秒。数字可以是一个整数常量,也可以是一个具有整数值的 :variablename 引用。
例子:
   \sleep 10 ms
         

比如,内置的 TCP-B 类的事务的完整定义类似于:

\set nbranches :scale
\set ntellers 10 * :scale
\set naccounts 100000 * :scale
\setrandom aid 1 :naccounts
\setrandom bid 1 :nbranches
\setrandom tid 1 :ntellers
\setrandom delta -5000 5000
BEGIN;
UPDATE accounts SET abalance = abalance + :delta WHERE aid = :aid;
SELECT abalance FROM accounts WHERE aid = :aid;
UPDATE tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
UPDATE branches SET bbalance = bbalance + :delta WHERE bid = :bid;
INSERT INTO history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
END;

这个脚本允许事务的每次循环都引用不同的,随机选取的行。(这个例子还说明了为啥每个子会话需要拥有自己的变量 -- 否则它们就不会各自修改不同的行。)

[编辑] 每事务的日志

如果使用了 -l 选项,pgbench 把每个事务花的时间写到 logfile 里。日志文件的名称会是:pgbench_log.nnn,这里的 nnn 是 pgbench 进程的 PID。日志的格式是:

   client_id transaction_no time file_no time_epoch time_us

这里的 time 是以微秒计的事务执行时间,file_no 表示使用了哪个脚本文件(在用 -f 声明了多个脚本文件的时候有用),time_epoch/time_us 是微秒计的 UNIX 纪元格式的事务完成时的时间戳(可用于创建一个带小数秒的 ISO 8601 的时间戳)。

下面是样例输出:

0 199 2241 0 1175850568 995598
0 200 2465 0 1175850568 998079
0 201 2513 0 1175850569 608
0 202 2038 0 1175850569 2663

[编辑] 好习惯

我们很容易用 pgbench 产生完全没意义的数字。下面是一些帮助你获取有用结果的原则。

首先,绝对不要相信只跑了几秒钟的测试。把 -t 设置增大到让运行足以跑上几分钟的水平,这样就可以把噪声给平均掉了。有时候你需要跑上几个小时才能获取可复现的数字。最好是让测试跑上几分钟,看看你的数值是否可复现。

对于缺省的 TPC-B 类的测试场景,初始的缩放因子(-s)应该至少和你试图运行的客户端数目(-c)一样大;否则你就实际上是在测量更新竞争。在 branches 表里只有 -s 行,而每个事务都想更新它们之一,所以大于 -s 的 -c 数值将无疑是有大量事务阻塞在等待其它事务上头。

缺省的测试场景也跟表自初始化以来它已经存在的时间有关:在表中积累的死去的行和无用的空间也会改变结果。要理解这些结果,你必须跟踪更新的总数以及何时发生清理。如果打开了 autovacuum,那么可能会看到测量出来的性能有不可预期的变化。

pgbench 的一个限制是在测试大量客户端会话的时候,它自己可能会成为瓶颈。这个问题可以通过在不同的数据库服务器上运行 pgbench 来缓解。或者是在不同的客户机器上并发地运行好几个 pgbench 来测试同一个数据库服务器。

Personal tools