Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17

pgbench

pgbench — 在 PostgreSQL 上运行基准测试

语法

pgbench -i [选项...] [数据库名称]

pgbench [选项...] [数据库名称]

说明

pgbench 是一个简单的程序,用于在 PostgreSQL 上运行基准测试。它会不断运行相同的 SQL 命令序列,可能在多个并发数据库会话中运行,然后计算平均事务率(每秒事务数)。默认情况下,pgbench 测试一个大致基于 TPC-B 的场景,其中每个事务涉及五个 SELECTUPDATEINSERT 命令。不过,你可以通过编写自己的事务脚本文件来轻松测试其他情况。

pgbench 的典型输出如下

transaction type: <builtin: TPC-B (sort of)>
scaling factor: 10
query mode: simple
number of clients: 10
number of threads: 1
maximum number of tries: 1
number of transactions per client: 1000
number of transactions actually processed: 10000/10000
number of failed transactions: 0 (0.000%)
latency average = 11.013 ms
latency stddev = 7.351 ms
initial connection time = 45.758 ms
tps = 896.967014 (without initial connection time)

前七行会报告一些最重要的参数设置。第六行会报告在带有序列化或死锁错误的事务中尝试的最大次数(有关更多信息,请参见故障和序列化/死锁重试)。第八行会报告已完成与预期的事务数(后者只是客户端数和每个客户端的事务数的乘积);除非运行在完成前失败或某些 SQL 命令失败,否则这两个值将相等。(在-T模式下,只会打印实际事务数。)下一行会报告因序列化或死锁错误而失败的事务数(有关更多信息,请参见故障和序列化/死锁重试)。最后一行会报告每秒事务数。

默认的类似 TPC-B 的事务测试要求在事先设置好特定表。pgbench应使用-i(初始化)选项调用来创建和填充这些表。(在您测试自定义脚本时,您不需要此步骤,但需要执行测试所需的任何设置。)初始化看起来像

pgbench -i [ other-options ] dbname

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

警告

pgbench -i会创建四张表pgbench_accountspgbench_branchespgbench_historypgbench_tellers,销毁有任何这些名称的现有表。如果您有这些名称的表,请务必小心地使用其他数据库!

在默认缩放因子1时,表最初包含如此多的行

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(指定自定义脚本文件)。请参见下方获取完整列表。

选项

以下内容分为三个子部分。在对数据库进行初始化和运行基准测试时使用了不同的选项,但在两种情况下,一些选项都是有用的。

初始化选项

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

[-d] dbname
[--dbname=]dbname #

指定要测试的数据库的名称。如果没有指定,则会使用环境变量PGDATABASE。如果没有设置,则会使用为连接指定的用户名。

-i
--initialize #

必须在初始化模式中调用。

-I init_steps
--init-steps=init_steps #

仅执行正常初始化步骤中的某一选定集合。 init_steps指定要执行的初始化步骤,每个步骤使用一个字符。每个步骤按照指定的顺序调用。default 值为 dtgvp。可用步骤为

d (丢弃) #

丢弃任何现有的pgbench表。

t (创建表) #

创建标准pgbench场景使用的表,即pgbench_accountspgbench_branchespgbench_historypgbench_tellers

gG (客户端或服务器端生成数据) #

生成数据并将其加载到标准表中,替换已存在的任何数据。

使用g(客户端数据生成),数据在pgbench客户端中生成,然后发送到服务器。这通过COPY大量使用客户端/服务器带宽。 pgbench使用版本 14 或更高版本的PostgreSQL中的FREEZE选项来加速后续VACUUM,但如果启用了分区,则pgbench_accounts表除外。如果启用了g,则在为所有表生成数据时,日志记录将每 100,000 行打印一条消息。

使用G(服务器端数据生成),只有少量的查询从pgbench客户端发送,然后数据实际在服务器中生成。这种变体不需要大量的带宽,但是服务器将执行更多工作。如果启用了G,则在生成数据时,日志记录将不会打印任何进度消息。

default 初始化行为使用客户端数据生成(等效于g)。

v (真空) #

在标准表格上调用 VACUUM

p (创建主鍵) #

在标准表格上创建主鍵索引。

f (创建外鍵) #

在标准表格之间创建外鍵约束。(请注意,此步骤默认不会执行。)

-F 填充系数
--fillfactor=填充系数 #

使用给定的填充系数创建 pgbench_accountspgbench_tellerspgbench_branches 表格。默认值为 100。

-n
--no-vacuum #

在初始化期间不执行真空吸尘。(即使在 -I 中指定了该选项,此选项也会抑制 v 初始化步骤。)

-q
--quiet #

切换日志记录到静默模式,每 5 秒只产生一条进度消息。默认日志记录功能每 100,000 行打印一条消息,这通常会每秒输出很多行(尤其是在优秀的硬件上)。

如果在 -I 中指定了 G,则此设置不起作用。

-s 缩放因子
--scale=缩放因子 #

将生成的行数乘以缩放因子。例如,-s 100 将在 pgbench_accounts 表格中创建 10,000,000 行。默认值为 1。当缩放比例为 20,000 或更大时,用于保存帐户标识符的列(aid 列)将切换为使用更大的整数(bigint),以便足够大以容纳帐户标识符的范围。

--foreign-keys #

在标准表格之间创建外鍵约束。(此选项会将 f 步骤添加到初始化步骤序列中,如果它尚不存在的话。)

--index-tablespace=索引表空间 #

在指定表空间而不是默认表空间中创建索引。

--partition-method=NAME #

使用名称方法创建一个分区pgbench_accounts表。预期值是范围hash。此选项要求--分区设置为非零。如果未指定,则默认值为范围

--分区=NUM #

使用NUM个近似相等大小的分区创建分区pgbench_accounts表,用于缩放帐号的数量。默认值为0,表示未分区。

--表空间=表空间 #

在指定表空间(而不是默认表空间)中创建表。

--未记录表 #

将所有表创建为未记录表,而不是永久性表。

基准测试选项

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

-b 脚本名称[@权重]
--内置=脚本名称[@权重] #

将指定的内置脚本添加到要执行的脚本列表中。可用的内置脚本有:tpcb-likesimple-updateselect-only。接受内置名称的不歧义前缀。使用特殊名称list显示内置脚本的列表并立即退出。

可选择在@后面编写整数权重,以调整选择此脚本与其他脚本的可能性。默认权重为 1。有关详细信息,请参见下文。

-c 客户端
--客户端=客户端 #

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

-C
--连接 #

为每个事务建立新连接,而不是针对每个客户端会话仅建立一次。这可用于测量连接开销。

-D 变量名称=
--定义=变量名称= #

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

-f 文件名[@权重]
--文件=文件名[@权重] #

将从 filename 读入的交易脚本添加到将要执行的脚本列表中。

或者,在 @ 之后编写一个整数权重,以调整选择该脚本而非其他脚本的可能性。默认权重为 1。(若要使用包含 @ 字符的脚本文件名,请追加一个权重以避免歧义,例如 filen@me@1。)有关详细信息,请参见下方。

-j 线程
--jobs=线程 #

pgbench 中的工作线程数。在多 CPU 机器上,使用多个线程可能会有所帮助。客户端在可用线程之间尽可能均匀地分布。默认值为 1。

-l
--log #

将有关每个交易的信息写入日志文件。有关详细信息,请参见下方。

-L 限制
--latency-limit=限制 #

持续时间超过 限制 毫秒的交易将被计算并单独报告,作为 迟到的

使用节流功能时 (--rate=...),落后于计划超过 限制 ms 且因此无法达到延迟限制的交易根本不会发送到服务器。它们会被计算并单独报告为 已跳过

使用 --max-tries 选项时,如果某个交易因序列化异常或死锁而失败,则当其所有尝试的总时间大于 限制 ms 时,将不再重试该交易。若只想限制尝试次数而不是尝试时间,请使用 --max-tries=0。默认情况下,--max-tries 选项设置为 1,不会重试遇到序列化/死锁错误的交易。有关重试此类交易的更多信息,请参见 故障、序列化和死锁重试

-M 查询模式
--protocol=查询模式 #

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

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

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

  • prepared:使用包含预处理语句的扩展查询协议。

prepared 模式中,pgbench 从第二次查询迭代开始重用解析分析结果,所以pgbench 运行速度比其他模式快。

默认为简单查询协议。(有关更多信息,请参见第 53 章。)

-n
--no-vacuum #

运行测试前不执行任何 vacuum 操作。如果您正在运行不包括标准表 pgbench_accountspgbench_branchespgbench_historypgbench_tellers 的自定义测试场景,则此选项非常必要

-N
--skip-some-updates #

运行内置的简易更新脚本。可以简写为 -b simple-update

-P
--progress= #

秒显示一次进度报告。报告包括自运行开始以来的时间、自上次报告以来的 TPS、事务延迟平均值、标准偏差,以及自上次报告以来的失败事务数。在节流期间(-R),延迟相对于事务计划的开始时间而非实际的事务开始时间而计算,因此它还包括平均调度滞后时间。当 --max-tries 用于在序列化/死锁错误后启用事务重试时,报告将包括重试事务数和所有重试的总和。

-r
--report-per-command #

基准完成后,报告每个命令的以下统计信息:每个语句的平均延迟(从客户端的角度来看的执行时间)、失败数和在此命令中序列化或死锁错误后的重试数。只有当 --max-tries 选项不等于 1 时,报告才会显示重试统计信息。

-R 速率
--rate=速率 #

执行针对指定速率的事务,而不是尽可能快地运行(默认值)。速率以每秒事务数表示。如果目标速率高于最大可能速率,速率限制将不会影响结果。

通过在基于泊松分布的时间表中启动事务来设定速率。预期的启动时间表会根据客户端第一次启动的时间点向前移动,而不是根据上个事务结束的时间点。这种方法意味着当事务超出其原始计划结束时间时,后面的事务有可能重新追赶上来。

在节流活动时,运行结束时报告的事务延迟计算自计划启动时间,因此其中包括各个事务为等待前一个事务完成而不得不等待的时间。此等待时间称为计划滞后时间,其平均值和最大值会另外报告。相对于实际事务启动时间的事务延迟(即在数据库中执行事务所花费的时间)可以通过从报告的延迟中减去计划滞后时间来计算。

如果将 --latency-limit--rate 同时使用,事务可能落后得很多,以至于在上一个事务结束时已经超过延迟限制(因为延迟是从计划启动时间计算的)。此类事务不会发送到服务器,但会完全跳过并单独计数。

高计划滞后时间表明系统无法以指定的速率使用所选的客户端和线程数处理事务。当平均事务执行时间长于每个事务之间的计划间隔时,依次执行的每个事务都会进一步落后,而且随着测试运行时间的增加,计划滞后时间会不断增加。出现这种情况时,你必须降低指定的的事务速率。

-s scale_factor
--scale=scale_factor #

pgbench 输出中报告指定比例因数。对于内置测试,这是不必要的;将通过计算 pgbench_branches 表中的行数检测到正确的比例因数。然而,在仅测试自定义基准测试 (-f 选项) 时,如果没有使用此选项,比例因数将被报告为 1。

-S
--select-only #

运行内置仅选择的脚本。 -b select-only 的简写。

-t transactions
--transactions=transactions #

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

-T seconds
--time=seconds #

按秒运行测试,而不是按每个客户端的事务数固定。-t-T 相互排斥。

-v
--vacuum-all #

在运行测试之前,对所有四个标准表进行 Vacuum。如果没有 -n-vpgbench 会对 pgbench_tellerspgbench_branches 表进行 Vacuum,并截断 pgbench_history 表。

--aggregate-interval=seconds #

聚合区间长度(以秒为单位)。只能与 -l 选项结合使用。使用此选项时,日志包含按区间划分的汇总数据,如下所述。

--exit-on-abort #

当由于某个错误导致任何客户端被中止时,立即退出。如果没有此选项,即使客户端被中止,其他客户端仍可以按 -t-T 选项指定的配置继续运行,在这种情况下,pgbench 会打印不完整的结果。

请注意,序列化失败或死锁失败不会中止客户端,因此不受此选项影响。有关详细信息,请参见 Failures and Serialization/Deadlock Retries

--failures-detailed #

在按事务和聚合日志以及在主报告和按脚本报告中报告失败,按以下类型分组

  • 序列化失败;

  • 死锁失败;

有关详细信息,请参见 Failures and Serialization/Deadlock Retries

--log-prefix=prefix #

设置 --log 创建的日志文件的目录前缀。默认值为 pgbench_log

--max-tries=number_of_tries #

允许对带有序列化/死锁错误的事务进行重试,并设置这些重试的最大次数。此选项可以与限制所有事务重试总时间的--latency-limit 选项结合使用;而且,如果没有 --latency-limit--time,则不能使用无限次数重试(--max-tries=0)。默认值为 1,并且不会重试带有序列化/死锁错误的事务。有关此类事务重试的更多信息,请参见 Failures and Serialization/Deadlock Retries

--progress-timestamp #

显示进度时(选项 -P),使用时间戳(Unix 时间戳),而不是自运行开始以来的秒数。单位为秒,小数点后面的精度为毫秒。这有助于比较由各种工具生成的日志。

--random-seed=seed #

设置随机生成器种子。对系统随机数生成器设置种子,该生成器生成一系列初始生成器状态,每个线程一个。值seed 可能为:time(默认值,种子基于当前时间)、rand(使用强随机源,如果找不到则失败)或无符号十进制整数值。随机生成器会从 pgbench 脚本(random... 函数)中显式调用或隐式调用(例如,选项 --rate 用它来调度事务)。显式设置时,用于设置种子的值显示在终端上。允许 seed 的任何值也可以通过环境变量 PGBENCH_RANDOM_SEED 提供。要确保提供的种子影响所有可能的用法,请首先放置此选项或使用环境变量。

显式设置种子允许在涉及随机数的范围内精确复制 pgbench 运行。由于随机状态按线程管理,这意味着在每个线程都有一个客户端且没有外部数据依赖项的情况下,对相同调用来说,完全相同的 pgbench 运行。从统计学的角度来看,精确复制运行是一个糟糕的想法,因为它会隐藏性能的可变性或不当地提高性能,例如,通过命中与先前运行相同的页面。然而,它对调试也可能很有帮助,例如,重新运行导致错误的棘手情况。请明智地使用。

--sampling-rate=rate #

采样率,用于在将数据写入日志时减少生成的日志量。如果指定了此选项,则只记录特定比例的事务。1.0 表示记录所有事务,0.05 表示仅记录 5% 的事务。

处理日志文件时记得要考虑采样率。例如,计算 TPS 值时,您需要相应地乘以指定数字(例如,对于 0.01 采样率,您只能获得实际 TPS 的 1/100)。

--show-script=脚本名 #

立即在 stderr 上显示内置脚本 脚本名 的实际代码,然后退出。

--verbose-errors #

打印有关所有错误和故障(不重试的错误)的消息,包括超出了针对重试的哪个限制以及对序列化/死锁故障的超出程度。(注意,在这种情况下,输出可能会显著增加。)有关更多信息,请参见 Failures and Serialization/Deadlock Retries

常见选项

pgbench 还接受以下常见的命令行参数,用于连接参数和其他常见设置

--debug #

打印调试输出。

-h 主机名
--host=主机名 #

数据库服务器的主机名

-p 端口
--port=端口 #

数据库服务器的端口号

-U 用户名
--username=用户名 #

作为其连接的用户名

-V
--version #

打印 pgbench 版本并退出。

-?
--help #

显示有关 pgbench 命令行参数的帮助信息,然后退出。

退出状态

成功运行将退出,状态为 0。退出状态 1 表示静态问题,例如无效的命令行选项或预期永不发生的内部错误。启动基准时发生的早期错误(例如初始连接失败),也会退出,状态为 1。运行期间的错误(例如数据库错误或脚本中的问题)将导致退出状态 2。在后一种情况下,如果未指定 --exit-on-abort 选项,pgbench 将打印部分结果。

环境

PGDATABASE
PGHOST
PGPORT
PGUSER #

默认连接参数。

此实用程序(就像大多数其他 PostgreSQL 实用程序一样)使用 libpq 支持的环境变量(请参见 第 32.15 节)。

环境变量 PG_COLOR 指定是否在诊断消息中使用颜色。可能的值为 alwaysautonever

备注

pgbench 中实际上执行的 事务 是什么?

pgbench 从指定列表中随机选择的测试脚本执行脚本。脚本可能包括使用 -b 指定的内置脚本以及使用 -f 指定的用户提供的脚本。可以为每个脚本指定一个 @ 后指定的相对权重,以更改其选择概率。默认权重为 1。权重为 0 的脚本会被忽略。

默认内置事务脚本(也可以使用 -b tpcb-like 调用)在随机选择的 aidtidbiddelta 上针对每个事务发布七个命令。此方案以 TPC-B 基准为灵感,但实际上并非 TPC-B,因此得名。

  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;

如果您选择 simple-update 内置(还包括 -N),步骤 4 和 5 将不会包含在事务中。这将避免对这些表进行更新争用,但这使得测试用例甚至不像 TPC-B。

如果你选择内置的 select-only(或者 -S),则只发出 SELECT

自定义脚本

pgbench 支持通过将默认事务脚本(上面已描述)替换为从文件读取的事务脚本(-f 选项)来运行自定义基准场景。在这种情况下,事务按一次脚本文件执行来计。

脚本文件包含以分号结尾的一个或多个 SQL 命令。空行和以 -- 开头的行将被忽略。脚本文件还可以包含 元命令,这些命令将由 pgbench 自行解释,如下所述。

注意

PostgreSQL 9.6 之前,脚本文件中的 SQL 命令以换行符结尾,因此它们无法跨行继续。现在分号是 必需的 用来分隔连续的 SQL 命令(但如果 SQL 命令后面跟着元命令,则不需要分号)。如果你需要创建同时适用于 pgbench 旧版本和新版本的脚本文件,请务必将每个 SQL 命令写在以分号结尾的单行中。

假设 pgbench 脚本不包含 SQL 事务的不完整块。如果在运行时客户端在未完成最后一个事务块的情况下到达脚本末尾,则将中止它。

脚本文件有一个简单的变量替换工具。变量名称必须由字母(包括非拉丁字母)、数字和下划线组成,第一个字符不能是数字。变量可以通过上述命令行 -D 选项或以下元命令来设置。除了由 -D 命令行选项预先设置的任何变量之外,还有一些自动预先设置的变量,这些变量列在 表 298 中。使用 -D 为这些变量指定的数值优先于自动预设值。一旦设置,可以通过编写 :变量名 将变量的值插入 SQL 命令中。在运行多个客户端会话时,每个会话都有自己的一组变量。pgbench 支持在一条语句中使用多达 255 个变量。

表 298. pgbench 自动变量

变量 说明
client_id 用于标识客户端会话的唯一编号(从零开始)
default_seed 默认情况下,哈希和伪随机排列函数中使用的种子
random_seed 随机生成器种子(除非使用 -D 覆盖)
scale 当前比例因子

脚本文件元命令以反斜杠 (\) 开头,通常一直延伸到行的末尾,但可以通过编写反斜杠换行来继续编写其他行。元命令的参数以空格分隔。支持这些元命令

\gset [前缀] \aset [前缀] #

这些命令可用于结束 SQL 查询,代替终止分号 (;)。

当使用 \gset 命令时,预计前一个 SQL 查询将返回一行,其列存储在以列名为名称的变量中,如果提供了前缀,则使用前缀 prefix

当使用 \aset 命令时,所有组合的 SQL 查询(以 \; 分隔)的列都存储在以列名为名称的变量中,如果提供了前缀,则使用前缀 prefix。如果查询未返回任何行,则不执行任何分配,并且可以测试变量的存在以检测到这一点。如果查询返回多行,则保留最后的值。

无法在管道模式下使用 \gset\aset,因为在需要命令的时间点查询结果尚未可用。

以下示例将第一个查询中的最终帐户余额存入变量 abalance,并使用第三个查询中的整数填充变量 p_twop_three。第二个查询的结果将被丢弃。最后两个组合查询的结果存储在变量 fourfive 中。

UPDATE pgbench_accounts
  SET abalance = abalance + :delta
  WHERE aid = :aid
  RETURNING abalance \gset
-- compound of two queries
SELECT 1 \;
SELECT 2 AS two, 3 AS three \gset p_
SELECT 4 AS four \; SELECT 5 AS five \aset
\if expression
\elif expression
\else
\endif #

这组命令实现了可嵌套的条件块,类似于 psql\if expression。条件表达式与 \set 的条件表达式相同,将非零值解释为 true。

\set varname expression #

设置变量 varname 为计算值 expression。在表达式中可能包含 NULL 常数、布尔常数 TRUEFALSE、整数常数,例如 5432、双精度常数,例如 3.14159、变量引用 :variablename操作符 和其正常 SQL 优先级和结合性、函数调用、SQL CASE 通用条件表达式 和括号。

函数和大多数操作符在 NULL 输入时返回 NULL

为了判断条件,非零数字值是 TRUE,零数字值和 NULLFALSE

过大或过小的整数和双精度常数以及整数算术操作符(+-*/)在溢出时引发错误。

如果没有在 CASE 中提供最终的 ELSE 子句,则默认值为 NULL

范例

\set ntellers 10 * :scale
\set aid (1021 * random(1, 100000 * :scale)) % \
           (100000 * :scale) + 1
\set divx CASE WHEN :x <> 0 THEN :y/:x ELSE NULL END
\sleep number [ us | ms | s ] #

使脚本执行在微秒 (us)、毫秒 (ms) 或秒 (s) 中睡眠指定持续时间。如果省略单位,则默认单位为秒。 number 可以是整数常数或 :variablename,引用具有整数值的变量。

范例

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

设置变量 varname 为带有给定 argument(s) 的 shell 命令 command 的结果。该命令必须通过其标准输出返回一个整数值。

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
\startpipeline
\syncpipeline
\endpipeline #

这一组命令实现了 SQL 语句的管道化。管道必须以 \startpipeline 开头,以 \endpipeline 结尾。其间可以任意数量的 \syncpipeline 命令,它会发送 同步消息,而不会结束正在进行的管道或刷新发送缓冲区。在管道模式下,可以使用户向服务器发送报表,而不会等待以前的报表结果。详情请参见 第 32.5 节。管道模式要求使用扩展查询协议。

内置运算符

此处列出的算术、位运算、比较和逻辑运算符 表 299 构建到 pgbench 中,可以用于出现在 \set 中的表达式中。运算符按优先级递增顺序列出。除非特别注明,否则若两个数字输入中的任一内容是双精度,则采取两个数字输入的运算符将生成一个双精度值,否则生成一个整数结果。

表 299. pgbench 运算符

运算符

说明

示例

boolean OR booleanboolean

逻辑或

5 or 0TRUE

boolean AND booleanboolean

逻辑与

3 and 0FALSE

NOT booleanboolean

逻辑非

not falseTRUE

boolean IS [NOT] (NULL|TRUE|FALSE)boolean

布尔值测试

1 is nullFALSE

value ISNULL|NOTNULLboolean

空值测试

1 notnullTRUE

number = numberboolean

等于

5 = 4FALSE

number <> numberboolean

不等于

5 <> 4TRUE

number != numberboolean

不等于

5 != 5FALSE

number < numberboolean

小于

5 < 4FALSE

number <= numberboolean

小于或等于

5 <= 4FALSE

number > numberboolean

大于

5 > 4TRUE

number >= numberboolean

大于或等于

5 >= 4TRUE

integer | integerinteger

按位或

1 | 23

integer # integerinteger

按位异或

1 # 32

integer & integerinteger

按位与

1 & 31

~ integerinteger

按位非

~ 1-2

integer << integerinteger

按位左移

1 << 24

integer >> integerinteger

按位右移

8 >> 22

数字 + 数字数字

加法

5 + 49

数字 - 数字数字

减法

3 - 2.01.0

数字 * 数字数字

乘法

5 * 420

数字 / 数字数字

除法(如果两个输入都是整数,则截断结果到零)

5 / 31

整数 % 整数整数

取模(余数)

3 % 21

- 数字数字

取反

- 2.0-2.0


内置函数

表 300 中列出的函数内置于 pgbench 中,可在 \set 中出现的表达式中使用。

表 300。pgbench 函数

函数

说明

示例

abs ( 数字 ) → 与输入相同的类型

绝对值

abs(-17)17

debug ( 数字 ) → 与输入相同的类型

将参数打印到 stderr,并返回参数。

debug(5432.1)5432.1

double ( 数字 ) → double

转换为 double。

double(5432)5432.0

exp ( 数字 ) → double

指数(以给定幂计算 e

exp(1.0)2.718281828459045

greatest ( 数字 [, ... ] ) → 如果任何参数为 double,则 double,否则 integer

选择参数中最大的值。

greatest(5, 4, 3, 2)5

hash ( value [, seed ] ) → 整数

这是 hash_murmur2 的别名。

hash(10, 5432)-5817877081768721676

hash_fnv1a ( value [, seed ] ) → 整数

计算 FNV-1a 哈希

hash_fnv1a(10, 5432)-7793829335365542153

hash_murmur2 ( value [, seed ] ) → 整数

计算 MurmurHash2 哈希

hash_murmur2(10, 5432)-5817877081768721676

int ( number ) → 整数

转换为整数。

int(5.4 + 3.8)9

least ( number [, ... ] ) → 双精度(如果有任何参数为双精度数),否则为 整数

选择参数中最小的值。

least(5, 4, 3, 2.1)2.1

ln ( number ) → 双精度数

自然对数

ln(2.718281828459045)1.0

mod ( integer, integer ) → 整数

取模(余数)

mod(54, 32)22

permute ( i, size [, seed ] ) → 整数

i 的置换值,范围为 [0, size)。这是 iseed 参数化整数 0...size-1 的伪随机排列中的新位置(模 size),见下文。

permute(0, 4)0 到 3 之间的整数

pi () → 双精度数

π 的近似值

pi()3.14159265358979323846

pow ( x, y ) → double

power ( x, y ) → double

x 提升到 y 的幂

pow(2.0, 10)1024.0

random ( lb, ub ) → integer

在一个统一分布随机整数,其范围在 [lb, ub].

random(1, 10)1 到 10 之间的整数

random_exponential ( lb, ub, parameter ) → integer

在一个 [lb, ub] 内计算出一个指数分布的随机整数,请参见以下内容。

random_exponential(1, 10, 3.0)1 到 10 之间的整数

random_gaussian ( lb, ub, parameter ) → integer

在一个 [lb, ub] 内计算出一个高斯分布的随机整数,请参见以下内容。

random_gaussian(1, 10, 2.5)1 到 10 之间的整数

random_zipfian ( lb, ub, parameter ) → integer

在一个 [lb, ub] 内计算出一个 Zipf 分布的随机整数,请参见以下内容。

random_zipfian(1, 10, 1.5)1 到 10 之间的整数

sqrt ( number ) → double

平方根

sqrt(2.0)1.414213562


random 函数使用均匀分布生成值,即所有这些值在指定的范围内以相等的概率绘制。 random_exponentialrandom_gaussianrandom_zipfian 函数需要附加的双精度参数来确定分布的精确形状。

  • 对于指数分布,parameter 通过在 parameter 上截断一个快速下降的指数分布,然后投影到边界之间的整数来控制分布。确切地说,对于


    f(x) = exp(-parameter * (x - min) / (max - min + 1)) / (1 - exp(-parameter))

    那么 em 类“可替换”i 在 em 类“可替换”min 和 em 类“可替换”max 之间的(包含)取值概率如下:f(i) - f(i + 1)

    直观上讲,em 类“可替换”parameter 越大,接近 em 类“可替换”min 的取值访问越多,接近 em 类“可替换”max 的取值访问越少。em 类“可替换”parameter 越接近 0,访问分布越平坦(越均匀)。这种分布的粗略近似值为,接近 em 类“可替换”min 的范围内最常出现的 1% 的取值在 em 类“可替换”parameter 的 time% 的时间内被选择出来。em 类“可替换”parameter 的值必须是严格正数。

  • 对于高斯分布,该区间被映射到一个标准正态分布(经典的钟形高斯曲线),且该分布在左侧以 -parameter 为截断点,在右侧以 +parameter 为截断点。区间中间的取值更有可能被选择。确切地说,如果 PHI(x) 是标准正态分布的累积分布函数,均值为 mu,定义为 (max + min) / 2.0,且


    f(x) = PHI(2.0 * parameter * (x - mu) / (max - min + 1)) /
           (2.0 * PHI(parameter) - 1)

    那么 em 类“可替换”i 在 em 类“可替换”min 和 em 类“可替换”max 之间的(包含)取值概率如下:f(i + 0.5) - f(i - 0.5)。直观上讲,em 类“可替换”parameter 越大,接近区间中间的取值越常被选择,接近 em 类“可替换”min 和 em 类“可替换”max 边界的取值越不常被选择。约 67% 的取值是从中间的 1.0 / parameter 中选择的,即均值周围的相对 0.5 / parameter,95% 的取值是从中间的 2.0 / parameter 中选择的,即均值周围的相对 1.0 / parameter;例如,如果 em 类“可替换”parameter 为 4.0,则区间中间的四分之一(1.0 / 4.0)(即 3.0 / 8.05.0 / 8.0)将选择约 67% 的取值,区间中间的一半(第二和第三四分位数)(2.0 / 4.0)将选择约 95% 的取值。允许的最小 em 类“可替换”parameter 值为 2.0。

  • random_zipfian 生成了一个有界的齐夫分布。参数 定义了分布的偏斜程度。参数 越大,绘制区间开始处的值的频率就越高。该分布为,假设该范围从 1 开始,绘制 k 与绘制 k+1 的概率之比为 ((k+1)/k)**parameter。例如,random_zipfian(1, ..., 2.5) 生成的值 1 的频率大约是 (2/1)**2.5 = 5.66 倍于 2,而后者生成的频率又是 (3/2)**2.5 = 2.76 倍于 3,依此类推。

    pgbench 的实现基于卢克·德沃伊的“非均匀随机变量生成”,第 550-551 页,施普林格 1986 年。由于该算法的限制,parameter 值限制在 [1.001, 1000] 范围内。

注意

在设计一个不均匀地选择行的基准时,请注意所选的行可能与其他数据相关,例如序列中的 ID 或物理行顺序,这可能会扭曲性能测量。

为避免这种情况,你可能希望使用 permute 函数或其他一些具有类似效果的附加步骤来随机选择行并消除此类关联。

哈希函数 hashhash_murmur2hash_fnv1a 接受一个输入值和一个可选种子参数。如果未提供种子,则使用 :default_seed 的值,该值随机初始化,除非由命令行 -D 选项设置。

permute 接受输入值、大小和可选种子参数。它生成范围内的整数的拟随机排列 [0, size),并返回排列值中输入值的索引。所选的排列由种子参数化,如果未指定,则该参数默认为 :default_seed。与哈希函数不同,permute 确保输出值中不存在冲突或空白。间隔之外的输入值将按模解释大小。如果大小为负,该函数将引发错误。可以使用 permute 来分散非均匀随机函数的分布,例如 random_zipfianrandom_exponential,这样更常绘制的值不会与相关性无关紧要。例如,以下 pgbench 脚本模拟了社交媒体和博客平台典型的可能真实世界工作负载,其中一些帐户会产生过大的负载

\set size 1000000
\set r random_zipfian(1, :size, 1.07)
\set k 1 + permute(:r, :size)

在某些情况下,需要多个不相互关联的独立分布,这时可选种子参数就派上用场了

\set k1 1 + permute(:r, :size, :default_seed + 123)
\set k2 1 + permute(:r, :size, :default_seed + 321)

也可以用 hash 近似类似的行为

\set size 1000000
\set r random_zipfian(1, 100 * :size, 1.07)
\set k 1 + abs(hash(:r)) % :size

但是,由于 hash 会产生碰撞,因此一些值将不可访问,而其他值将比从原始分布预期的值更频繁。

例如,内置类 TPC-B 事务的完整定义是

\set aid random(1, 100000 * :scale)
\set bid random(1, 1 * :scale)
\set tid random(1, 10 * :scale)
\set delta random(-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;

此脚本允许事务的每个迭代引用不同的随机选择的行。(此示例还说明了每个客户端会话拥有自己的变量非常重要的原因 — 否则它们将不可能独立接触不同的行。)

每笔交易日志

使用 -l 选项(但未使用 --aggregate-interval 选项),pgbench 会将有关每笔交易的信息写入日志文件。日志文件将命名为 prefix.nnn,其中 prefix 默认为 pgbench_lognnnpgbench 进程的 PID。可以通过使用 --log-prefix 选项来更改前缀。如果 -j 选项为 2 或更大,以便有多个工作线程,则每个线程将有自己的日志文件。第一个工作线程将为其日志文件使用与标准单工作线程情况下相同的文件名。其他工作线程的附加日志文件将命名为 prefix.nnn.mmm,其中 mmm 是每个工作线程的顺序号,从 1 开始。

日志文件中的每行描述一个事务。它包含以下空格分隔字段

client_id

标识运行该事务的客户端会话

transaction_no

计数该会话运行了多少事务

time

事务的经过时间(以微秒为单位)

script_no

标识用于该事务的脚本文件(在使用 -f-b 指定多个脚本时很有用)

time_epoch

事务完成时间,以 Unix 时间戳格式

time_us

事务完成时间的微秒部分

schedule_lag

事务开始延迟,即事务预定开始时间与实际开始时间之差(以微秒为单位)(仅在指定 --rate 时显示)

retries

事务期间序列化或死锁错误后的重试次数(仅在 --max-tries 不等于 1 时显示)

同时在 --rate--latency-limit 中使用时,time 的跳过事务将报告为 skipped。如果事务以失败告终,其 time 将报告为 failed。如果使用 --failures-detailed 选项,则失败事务的 time 将报告为 serializationdeadlock,具体取决于故障类型(有关更多信息,请参见 Failures and Serialization/Deadlock Retries

以下是一个单客户端运行中生成的日志文件片段

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

另一个带有 --rate=100--latency-limit=5 的示例(注意额外的 schedule_lag 列)

0 81 4621 0 1412881037 912698 3005
0 82 6173 0 1412881037 914578 4304
0 83 skipped 0 1412881037 914578 5217
0 83 skipped 0 1412881037 914578 5099
0 83 4722 0 1412881037 916203 3108
0 84 4142 0 1412881037 918023 2333
0 85 2465 0 1412881037 919759 740

在此示例中,事务 82 延迟了,因为其延迟(6.173 毫秒)超过了 5 毫秒的限制。由于在开始之前就已经延迟,因此跳过了接下来 2 个事务。

以下示例显示了包含失败和重试的日志文件片段,其中将最大尝试次数设置为 10(请注意额外的 retries 列)

3 0 47423 0 1499414498 34501 3
3 1 8333 0 1499414498 42848 0
3 2 8358 0 1499414498 51219 0
4 0 72345 0 1499414498 59433 6
1 3 41718 0 1499414498 67879 4
1 4 8416 0 1499414498 76311 0
3 3 33235 0 1499414498 84469 3
0 0 failed 0 1499414498 84905 9
2 0 failed 0 1499414498 86248 9
3 4 8307 0 1499414498 92788 0

如果使用 --failures-detailed 选项,则失败类型将如下所述报告在 time

3 0 47423 0 1499414498 34501 3
3 1 8333 0 1499414498 42848 0
3 2 8358 0 1499414498 51219 0
4 0 72345 0 1499414498 59433 6
1 3 41718 0 1499414498 67879 4
1 4 8416 0 1499414498 76311 0
3 3 33235 0 1499414498 84469 3
0 0 serialization 0 1499414498 84905 9
2 0 serialization 0 1499414498 86248 9
3 4 8307 0 1499414498 92788 0

在能够处理大量事务的硬件上运行长时间测试时,日志文件可能会变得非常大。可以使用 --sampling-rate 选项仅记录事务的随机样本。

聚合日志记录

使用 --aggregate-interval 选项,日志文件使用不同的格式。每行日志描述一个聚合间隔。它包含以下空格分隔字段

interval_start

间隔的开始时间,以 Unix 纪元时间戳表示

num_transactions

间隔内的事务数

sum_latency

事务延迟总和

sum_latency_2

事务延迟平方和

min_latency

最低的事务延迟

max_latency

最高的事务延迟

sum_lag

事务开始延迟总和(除非指定 --rate,否则为零)

sum_lag_2

事务开始延迟平方和(除非指定 --rate,否则为零)

min_lag

最低的事务开始延迟(除非指定 --rate,否则为零)

max_lag

最高的事务开始延迟(除非指定 --rate,否则为零)

skipped

由于开始太迟而跳过的交易数量(除非指定 --rate--latency-limit,否则为零)

retried

重试的事务数量(除非 --max-tries 不等于一,否则为零)

retries

序列化或死锁错误后的重试次数(除非 --max-tries 不等于一,否则为零)

serialization_failures

序列化错误,且随后未重试的交易数量(除非指定 --failures-detailed,否则为零)

deadlock_failures

死锁错误,且随后未重试的交易数量(除非指定 --failures-detailed,否则为零)

以下是一些由此选项生成的示例输出

pgbench --aggregate-interval=10 --time=20 --client=10 --log --rate=1000 --latency-limit=10 --failures-detailed --max-tries=10 test

1650260552 5178 26171317 177284491527 1136 44462 2647617 7321113867 0 9866 64 7564 28340 4148 0
1650260562 4808 25573984 220121792172 1171 62083 3037380 9666800914 0 9998 598 7392 26621 4527 0

请注意,虽然普通(未聚合)日志格式显示了每个事务使用的脚本,但聚合格式并未显示。因此,如果您需要每个脚本的数据,则需要自己聚合数据。

按语句报告

使用 -r 选项,pgbench 为每个报表收集以下统计数据

  • latency — 每个报表已执行事务的时间。pgbench 报告报表所有成功运行的平均值。

  • 此报表中的失败次数。有关详细信息,请参阅 失败和序列化/死锁重试

  • 此报表中序列化或死锁错误后的重试次数。有关详细信息,请参阅 失败和序列化/死锁重试

仅当 --max-tries 选项不等于 1 时,报表才会显示重试统计信息。

每个客户端执行的每个报表的所有值均计算在内,并且会在基准测试完成后报告。

对于默认脚本,输出类似于以下内容

starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 1
query mode: simple
number of clients: 10
number of threads: 1
maximum number of tries: 1
number of transactions per client: 1000
number of transactions actually processed: 10000/10000
number of failed transactions: 0 (0.000%)
number of transactions above the 50.0 ms latency limit: 1311/10000 (13.110 %)
latency average = 28.488 ms
latency stddev = 21.009 ms
initial connection time = 69.068 ms
tps = 346.224794 (without initial connection time)
statement latencies in milliseconds and failures:
   0.012  0  \set aid random(1, 100000 * :scale)
   0.002  0  \set bid random(1, 1 * :scale)
   0.002  0  \set tid random(1, 10 * :scale)
   0.002  0  \set delta random(-5000, 5000)
   0.319  0  BEGIN;
   0.834  0  UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
   0.641  0  SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
  11.126  0  UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
  12.961  0  UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
   0.634  0  INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
   1.957  0  END;

使用可序列化的默认事务隔离级别(PGOPTIONS='-c default_transaction_isolation=serializable' pgbench ...)的默认脚本的另一个输出示例

starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 1
query mode: simple
number of clients: 10
number of threads: 1
maximum number of tries: 10
number of transactions per client: 1000
number of transactions actually processed: 6317/10000
number of failed transactions: 3683 (36.830%)
number of transactions retried: 7667 (76.670%)
total number of retries: 45339
number of transactions above the 50.0 ms latency limit: 106/6317 (1.678 %)
latency average = 17.016 ms
latency stddev = 13.283 ms
initial connection time = 45.017 ms
tps = 186.792667 (without initial connection time)
statement latencies in milliseconds, failures and retries:
  0.006     0      0  \set aid random(1, 100000 * :scale)
  0.001     0      0  \set bid random(1, 1 * :scale)
  0.001     0      0  \set tid random(1, 10 * :scale)
  0.001     0      0  \set delta random(-5000, 5000)
  0.385     0      0  BEGIN;
  0.773     0      1  UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
  0.624     0      0  SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
  1.098   320   3762  UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
  0.582  3363  41576  UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
  0.465     0      0  INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
  1.933     0      0  END;

如果指定了多个脚本文件,程序会分别为每个脚本文件报告所有统计信息。

请注意,收集所需的其他时序信息以进行每条语句的延迟计算会增加一些开销。这会降低平均执行速度,并降低 TPS 计算值。开销增大的幅度因平台和硬件而异。比较启用和禁用延迟报告时的平均 TPS 值,是衡量时序开销是否显著的一种不错的方法。

故障和序列化/死锁重试

执行 pgbench 时有三种主要类型的错误

  • pgbench 主程序的错误。这些错误最严重,并且总是会导致 pgbench 立刻退出,并显示相应的错误消息。其中包括

    • pgbench 开始时的错误(例如,无效的选项值);

    • 初始化模式中的错误(例如,用于为内置脚本创建表的查询失败);

    • 启动线程之前的错误(例如,无法连接到数据库服务器,元命令中的语法错误,线程创建失败);

    • 内部 pgbench 错误(理论上永远不会发生...)。

  • 线程管理其客户端时的错误(例如,客户端无法启动到数据库服务器的连接 / 用于将客户端连接到数据库服务器的套接字已失效)。在这些情况下,此线程的所有客户端都会停止,而其他线程将继续工作。但是,如果指定了 --exit-on-abort,在这种情况下,所有线程都将立即停止。

  • 直接客户端错误。如果遇到内部 pgbench 错误(理论上永远不会发生...)或指定了 --exit-on-abort,则这些错误会导致 pgbench 立刻退出,并显示相应的错误消息。否则,最坏的情况下只有出错的客户端会中止,而其他客户端会继续运行(但某些客户端的错误会在不中止客户端的情况下处理,并另外报告,参阅下文)。本节后面的内容假设讨论的错误仅为直接客户端错误,而不是内部 pgbench 错误。

发生严重错误时会中止客户端运行;例如,与数据库服务器的连接丢失或脚本结束时未完成上次事务。此外,如果执行 SQL 或 meta 命令失败的原因不是序列化或死锁错误,那么客户端会中止。否则,如果 SQL 命令因序列化或死锁错误而失败,那么客户端不会中止。在这些情况下,将回滚当前事务,其中包括将客户端变量设置为在运行本事务之前的值(假定一个事务脚本当中只包含一个事务;有关详细信息,请参阅 “事务”实际上在 pgbench 中执行了什么?)。带有序列化或死锁错误的事务将在回滚之后重复,直到成功完成或达到最大尝试次数(由 --max-tries 选项指定)/最大重试时间(由 --latency-limit 选项指定)/基准结束(由 --time 选项指定)。如果上次试运行失败,则此事务将报告为失败,但客户端不会中止并且会继续工作。

注意

如果没有指定 --max-tries 选项,则事务在序列化或死锁错误之后将永远不会重试,因为其默认值为 1。使用无限次数的尝试 (--max-tries=0) 和 --latency-limit 选项来仅限制最大尝试时间。还可以在无限次数的尝试下使用 --time 选项来限制基准持续时间。

重复包含多个事务的脚本时要小心:始终从头到尾重试脚本,因此成功的事务可能会执行多次。

在重复带有 shell 命令的事务时要小心。与 SQL 命令的结果不同,不回滚 shell 命令的结果,除了 \setshell 命令的变量值。

成功事务的延迟包括带回滚和重试的事务执行的整个时间。仅针对成功的事务和命令而不是针对失败的事务或命令测量延迟。

主要报告包含失败事务的数量。如果 --max-tries 选项不等于 1,那么主要报告还包含与重试相关的统计信息:重试事务的总数和重试总数。每个脚本报告从主要报告继承所有这些字段。每个语句报告仅当 --max-tries 选项不等于 1 时才显示重试统计信息。

若要在每个事务和聚合日志中按基本类型对失败进行分组,以及在主和每个脚本报告中进行分组,请使用 --failures-detailed 选项。如果您还想按类型区分所有错误和失败(未重试错误),包括超过重试限制的限制以及序列化/死锁失败超过的限制,请使用 --verbose-errors 选项。

表访问方法

您可以为此 pgbench 表指定 表访问方法。环境变量 PGOPTIONS 指定通过命令行传递给 PostgreSQL 的数据库配置选项(请参见 第 19.1.4 节)。例如,可以为 pgbench 创建的名为 wuzza 的表指定假设的默认表访问方法,如下所示:

PGOPTIONS='-c default_table_access_method=wuzza'

良好实践

pgbench 非常容易用于产生完全没有意义的数字。以下是一些指导原则,用于帮助你获得有用的结果。

首先,绝不要相信仅运行几秒钟的任何测试。使用 -t-T 选项使运行至少持续几分钟,以平均掉噪声。在某些情况下,可能需要数小时才能获得可复制的数字。最好对测试运行执行几次尝试,以了解你的数字是否可复制。

对于默认的类似 TPC-B 的测试场景,初始化比例因子 (-s) 应至少与打算测试的最大客户端数量 (-c) 一样大;否则,你将在很大程度上衡量更新争用。在 pgbench_branches 表中只有 -s 行,并且每个事务希望更新其中一行,因此,超过 -s-c 值无疑会导致许多事务因等待其他事务而被阻塞。

默认测试场景还对初始化表的时间长度非常敏感:表中死行和死空间的积累会改变结果。要了解结果,你必须跟踪总数更新和执行 vacuum 的时间。如果启用了自动 vacuum,则可能导致测量性能发生不可预测的变化。

pgbench 的一个限制是,它在尝试测试大量客户端会话时本身可能成为瓶颈。尽管低网络延迟至关重要,但可以通过在不同于数据库服务器上的机器上运行 pgbench 来缓解此问题。甚至可能在多台客户端计算机上同时运行多个 pgbench 实例,针对同一数据库服务器。

安全性

如果不受信任的用户可以访问尚未采用 安全模式用法模式 的数据库,请勿在该数据库中运行 pgbenchpgbench 使用不合格的名称,并不操作搜索路径。