↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3
历史版本PostgreSQL 8.3 已于 2013 年 2 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

F.18. pgbench #

pgbench是一个用于对PostgreSQL执行基准测试的简单程序。它会反复执行同一组 SQL 命令,也可在多个并发数据库会话中运行,然后计算平均事务速率(每秒事务数)。默认情况下,pgbench测试的是一个大体上基于 TPC-B 的场景,每个事务包含五条SELECT、UPDATE和INSERT命令。不过,通过编写自己的事务脚本文件,也很容易测试其他场景。

下面是 pgbench 的典型输出:

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)

前四行只是报告了一些最重要的参数设置。下一行报告已完成的事务数和 预期的事务数(后者就是客户端数与每个客户端的事务数的乘积); 除非运行在完成前失败,否则这两个数应该相等。最后两行报告每秒 事务数,分别计入和不计入启动数据库会话的时间。

F.18.1. 概述

默认的类 TPC-B 事务测试要求预先建立特定的表。应使用 -i(初始化)选项调用 pgbench 来创建并填充这些表。(测试 自定义脚本时不需要这一步,但需要自行完成测试所需的准备工作。) 初始化命令如下:

pgbench -i [ other-options ] dbname

其中 dbname 是要在其中进行测试的已创建 数据库的名称。(可能还需要 -h、 -p 和/或 -U 选项来指定如何连接数据库服务器。)

小心

pgbench -i会创建四个表accounts、 branches、history和tellers,并销毁任何已存在的同名表。如果数据库中已经存在这些名称的表,请务必改用其他数据库!

在默认的 1 倍“缩放因子”下,各表最初包含的行数如下:

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

你可以(而且对于大多数用途来说,也许应该)使用 -s(缩放因子)选项增加行数。此时还可以使用 -F(填充因子)选项。

完成必要的设置之后,就可以用不带 -i 的命令运行基准测试,即

pgbench [ options ] dbname

几乎在所有情况下,都需要一些选项才能做出有意义的测试。最重要 的选项是 -c(客户端数量)、 -t(事务数量)和 -f(指定自定义脚本文件)。 完整列表见下文。

表 F.14 给出数据库初始化期间使用的 选项,表 F.15 给出运行基准测试期间 使用的选项,而 表 F.16 给出两种情况下都有用的 选项。

表 F.14. pgbench 初始化选项

选项 描述
-i 调用初始化模式时必需。
-s scale_factor 将生成的行数乘以缩放因子。例如,-s 100 会在 accounts 表中创建 10,000,000 行。默认值为 1。
-F 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 运行测试前不执行清理。如果运行的自定义测试场景不包含 标准表 accounts、 branches、history 和 tellers,则此选项是 必需的。
-v 运行测试前清理全部四个标准表。若既不指定 -n 也不指定 -v,pgbench 将清理 tellers 和 branches 表,并截断 history。
-D varname=value 为自定义脚本定义一个变量(见下文)。允许使用多个 -D 选项。
-C 为每个事务建立一个新的连接,而不是每个客户端线程只建立一次。 这有助于测量连接开销。
-l 将每个事务所耗时间写入日志文件。详见下文。
-s scale_factor 在 pgbench 的输出中报告指定的缩放 因子。对于内置测试,这不是必需的;正确的缩放因子会通过统计 branches 表中的行数检测出来。但是, 在测试自定义基准(-f 选项)时,除非使用此选项, 否则缩放因子将报告为 1。
-d 打印调试输出。

表 F.16. pgbench 常用选项

选项 描述
-h hostname 数据库服务器的主机名
-p port 数据库服务器的端口号
-U login 用于连接的用户名

F.18.2. 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。

F.18.3. 自定义脚本

pgbench 支持运行自定义基准场景,方法 是用从文件读取的事务脚本( -f 选项)替换(前文所述的)默认事务脚本。 在这种情况下,一次“事务”算作脚本文件的一次执行。 甚至可以指定多个脚本(多个 -f 选项),此时每次客户端会话开始新事务时, 都会随机选择其中一个脚本。

脚本文件的格式是每行一条 SQL 命令;不支持跨多行的 SQL 命令。空行以及以--开头的行会被忽略。脚本文件的行还可以是“元命令”,它们由pgbench自身解释,详见下文。

脚本文件有一个简单的变量替换设施。变量可以通过命令行 -D 选项(前文已说明)或下文说明的元命令来 设置。除了由 -D 命令行选项预设的变量之外,变量 scale 会被预设为当前缩放因子。变量一经设置, 就可以通过写成 :variablename 把它的值 插入 SQL 命令中。运行多个客户端会话时,每个会话都有自己的一组 变量。

脚本文件中的元命令以反斜线(\)开头。元命令的参数以空白分隔。支持的元命令如下:

\set varname operand1 [ operator operand2 ]

将变量varname设置为一个计算出的整数值。每个operand要么是一个整数常量,要么是一个对具有整数值的变量的:variablename引用。operator可以是+、-、*或/。

示例:

\set ntellers 10 * :scale
\setrandom varname min max

将变量varname设置为介于min和max之间(含边界)的一个随机整数值。每个界限既可以是整数常量,也可以是指向某个整数值变量的:variablename引用。

示例:

\setrandom aid 1 :naccounts
\sleep number [ us | ms | s ]

让脚本执行休眠指定时长,单位可以是微秒(us)、毫秒(ms)或秒(s)。如果省略单位,则默认为秒。number可以是整数常量,也可以是引用了整数值变量的:variablename。

示例:

\sleep 10 ms

作为一个示例,内置的类 TPC-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;

该脚本允许事务的每次迭代都引用不同的随机选中行。(这个示例也说明了为什么每个客户端会话都必须拥有自己的变量 — 否则它们就无法彼此独立地访问不同的行。)

F.18.4. 每事务日志

使用 -l 选项时,pgbench 会把每个事务所耗时间写入日志文件。日志文件名为 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 epoch 格式的时间戳和以微秒计的偏移量(适合用于构造 带小数秒的 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
   

F.18.5. 良好实践

很容易用pgbench得出完全没有意义的数字。下面给出一些有助于获得有用结果的准则。

首先,绝不要相信任何只运行几秒钟的测试。 把 -t 设置得足够大,让运行至少持续几分钟,以平均掉噪声。 在某些情况下,可能需要数小时才能获得可重现的数字。最好把 测试多运行几次,看看你的数字是否可重现。

对于默认的类 TPC-B 测试场景,初始化缩放因子 (-s)至少应与你打算测试的最大客户端数 (-c)一样大;否则你测到的将主要是更新争用。 branches 表中只有 -s 行,而每个事务都要更新其中一行,因此 -c 值超过 -s 无疑会导致大量事务阻塞等待其他事务。

默认测试场景还会对表初始化后的时间长短非常敏感:表中死元组和无效空间的累积会改变结果。要理解这些结果,必须跟踪更新总数以及何时发生清理。如果启用了自动清理,它可能会给测得的性能带来不可预测的变化。

pgbench的一个局限是:在尝试测试大量客户端会话时,它自己也可能成为瓶颈。可以通过在与数据库服务器不同的机器上运行pgbench来缓解这一点,不过网络延迟必须足够低。甚至可以在多台客户端机器上同时运行多个pgbench实例,对同一台数据库服务器施压。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。