选择 打开 改范围 完整检索页

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
历史版本PostgreSQL 9.1 已于 2016 年 10 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本

F.26. pgbench #

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

下面是 pgbench 的典型输出:

transaction type: TPC-B (sort of)
scaling factor: 10
query mode: simple
number of clients: 10
number of threads: 1
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)

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

F.26.1. 概述

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

pgbench -i [ other-options ] dbname

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

小心

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

At the default scale factor of 1, the tables initially contain this many rows:

table                   # of rows
---------------------------------
pgbench_branches        1
pgbench_tellers         10
pgbench_accounts        100000
pgbench_history         0

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

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

pgbench [ options ] dbname

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

第 F.26.2 节 给出数据库初始化期间使用的 选项,第 F.26.3 节 给出运行基准测试期间 使用的选项,而 第 F.26.4 节 给出两种情况下都有用的 选项。

F.26.2. pgbench 初始化选项 #

pgbench 接受以下命令行初始化参数:

-i

进入初始化模式所必需。

-F fillfactor

以给定的 fillfactor 创建pgbench_accountspgbench_tellerspgbench_branches表。 默认值为 100。

-s scale_factor

将生成的行数乘以缩放因子。例如, -s 100 会在 pgbench_accounts 表中创建 10,000,000 行。默认值为 1。

F.26.3. pgbench Benchmarking Options #

pgbench 接受以下命令行基准测试参数:

-c clients

模拟的客户端数量,也就是并发数据库会话的数量。默认值为 1。

-C

为每个事务建立一个新的连接,而不是每个客户端会话只建立一次。 这有助于测量连接开销。

-d

打印调试输出。

-D varname=value

为自定义脚本定义一个变量(见下文)。允许使用多个 -D 选项。

-f filename

filename 读取事务脚本。详见下文。 -N-S-f 互斥。

-j threads

pgbench 内的工作线程数。在多 CPU 机器上使用多个线程会有帮助。客户端数必须时线程数的 整数倍,因为每个线程都会分到相同数量的客户端会话来管理。 默认值为 1。

-l

将每个事务所耗时间写入日志文件。详见下文。

-M querymode

用于向服务器提交查询的协议:

  • simple:使用简单查询协议。

  • extended:使用扩展查询协议。

  • prepared:使用带预备语句的扩展查询协议。

The default is simple query protocol. (See 第 46 章 for more information.)

-n

运行测试前不执行清理。如果你运行的自定义测试场景不包含 标准表 pgbench_accountspgbench_branchespgbench_historypgbench_tellers,则此选项是 必需的

-N

不更新 pgbench_tellerspgbench_branches。这会避免在这些表上 发生更新争用,但也会让该测试场景更不像 TPC-B。

-r

在基准测试完成后,报告每条命令的平均语句延迟(从客户端视角看到的执行时间)。详情见下文。

-s scale_factor

pgbench 的输出中报告指定的缩放 因子。对于内置测试,这不是必需的;正确的缩放因子会通过统计 pgbench_branches 表中的行数检测出来。 但是,在测试自定义基准( -f 选项)时,除非使用此选项,否则缩放因子 将报告为 1。

-S

执行只读 SELECT 事务,而不是类 TPC-B 测试。

-t transactions

每个客户端运行的事务数。默认值为 10。

-T seconds

让测试运行这么多秒,而不是每个客户端固定数量的事务。 -t-T 互斥。

-v

运行测试前清理全部四个标准表。若既不指定 -n 也不指定 -v,pgbench 将清理 pgbench_tellerspgbench_branches 表,并截断 pgbench_history

F.26.4. pgbench Common Options #

pgbench 接受以下通用命令行参数:

-h hostname

数据库服务器的主机名。

-p port

数据库服务器的端口号。

-U login

用于连接的用户名

F.26.5. 在 pgbench 中实际执行的事务是什么?

默认的事务脚本在每个事务中发出七条命令:

  1. BEGIN;

  2. UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;

  3. SELECT abalance FROM pgbench_accounts WHERE aid = :aid;

  4. UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;

  5. UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;

  6. INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);

  7. END;

如果指定-N,事务中将不包含第 4 步和第 5 步。如果指定-S,则只执行SELECT

F.26.6. 自定义脚本

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设置为介于minmax之间(含边界)的一个随机整数值。每个界限既可以是整数常量,也可以是指向某个整数值变量的:variablename引用。

示例:

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

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

示例:

\sleep 10 ms
\setshell varname command [ argument ... ]

将变量varname设置为 shell 命令command的结果。该命令必须通过标准输出返回一个整数值。

argument可以是文本常量,也可以是指向任意类型变量的:variablename引用。如果要使用以冒号开头的argument,需要在argument开头再添加一个冒号。

示例:

\setshell variable_to_be_assigned command literal_argument :variable ::literal_starting_with_colon
\shell command [ argument ... ]

\setshell相同,但结果会被忽略。

示例:

\shell command literal_argument :variable ::literal_starting_with_colon

作为一个示例,内置的类 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 pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
END;

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

F.26.7. 逐事务日志记录

使用 -l 选项时,pgbench 会把每个事务所耗时间写入日志文件。日志文件名为 pgbench_log.nnn, 其中 nnn 是 pgbench 进程的 PID。如果 -j 选项为 2 或更高(创建多个工作线程), 每个线程都会有自己的日志文件。第一个工作线程的日志文件名与 标准单工作线程情形相同。其余工作线程的额外日志文件名为 pgbench_log.nnn.mmm, 其中 mmm 是从 1 开始的各工作线程顺序编号。

日志格式如下:

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

F.26.8. 逐语句延迟

使用-r选项时,pgbench会收集每个客户端执行的每条语句所经过的事务时间。基准测试完成后,它会报告这些值的平均值,称为每条语句的延迟。

对于默认脚本,输出与下面类似:

starting vacuum...end.
transaction type: TPC-B (sort of)
scaling factor: 1
query mode: simple
number of clients: 10
number of threads: 1
number of transactions per client: 1000
number of transactions actually processed: 10000/10000
tps = 618.764555 (including connections establishing)
tps = 622.977698 (excluding connections establishing)
statement latencies in milliseconds:
        0.004386        \set nbranches 1 * :scale
        0.001343        \set ntellers 10 * :scale
        0.001212        \set naccounts 100000 * :scale
        0.001310        \setrandom aid 1 :naccounts
        0.001073        \setrandom bid 1 :nbranches
        0.001005        \setrandom tid 1 :ntellers
        0.001078        \setrandom delta -5000 5000
        0.326152        BEGIN;
        0.603376        UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
        0.454643        SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
        5.528491        UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
        7.335435        UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
        0.371851        INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
        1.212976        END;

如果指定了多个脚本文件,则会分别为每个脚本文件报告平均值。

注意,为逐语句延迟计算收集额外的计时信息会带来一定开销。这会拖慢平均执行速度,并降低计算出的 TPS。减速幅度在很大程度上取决于平台和硬件。比较启用和未启用延迟报告时的平均 TPS 值,是判断这一计时开销是否显著的好方法。

F.26.9. 良好实践

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

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

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

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

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

提交更正

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