Caution

pgbench

pgbench —在 PostgreSQL 上运行基准测试

Synopsis

pgbench -i [ option ...] [ dbname ]

pgbench [ option ...] [ dbname ]

Description

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
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)

前六行报告一些最重要的参数设置。下一行报告已完成和打算进行的 Transaction 数量(后者仅是 Client 数量与每个 ClientTransaction 数量的乘积);除非运行在完成前失败,否则它们将相等。 (在-T模式下,仅打印实际的事务数.)最后两行报告每秒的事务数,计算有无开始数据库会话的时间。

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

pgbench -i [ other-options ] dbname

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

Warning

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(Client 数量),-t(Transaction 数量),-T(时间限制)和-f(指定自定义脚本文件)。请参阅下面的完整列表。

Options

以下分为三个小节:在数据库初始化期间使用不同的选项,并且在运行基准测试时,在两种情况下都有用的选项。

Initialization Options

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

  • -i
    --initialize

    • 调用初始化模式时需要。
  • -F fillfactor
    --fillfactor= fillfactor

    • 使用给定的 fillfactor 创建pgbench_accountspgbench_tellerspgbench_branches表。默认值为 100.
  • -n
    --no-vacuum

    • 初始化后不进行任何清理。
  • -q
    --quiet

    • 将日志记录切换到安静模式,每 5 秒仅生成一条进度消息。默认日志记录每 100000 行打印一条消息,该消息通常每秒输出许多行(尤其是在良好的硬件上)。
  • -s scale_factor
    --scale= scale_factor

    • 将比例因子生成的行数相乘。例如,-s 100将在pgbench_accounts表中创建 10,000,000 行。默认值为 1.如果小数位数为 20,000 或更大,则用于容纳帐户标识符的列(aid列)将切换为使用较大的整数(bigint),以使其足够大以容纳帐户标识符的范围。
  • --foreign-keys

    • 在标准表之间创建外键约束。
  • --index-tablespace=index_tablespace

    • 在指定的表空间而不是默认表空间中创建索引。
  • --tablespace=tablespace

    • 在指定的表空间而不是默认表空间中创建表。
  • --unlogged-tables

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

Benchmarking Options

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

  • -b scriptname[@weight]
    --builtin = scriptname[@weight]

    • 将指定的内置脚本添加到已执行脚本的列表中。 @之后的可选整数权重允许调整绘制脚本的概率。如果未指定,则将其设置为 1.可用的内置脚本为:tpcb-likesimple-updateselect-only。接受内置名称的明确前缀。使用特殊名称list,显示内置脚本列表并立即退出。
  • -c clients
    --client= clients

    • 模拟的 Client 端数,即并发数据库会话数。默认值为 1.
  • -C
    --connect

    • 为每个事务构建一个新的连接,而不是在每个 Client 端会话中仅进行一次。这对于测量连接开销很有用。
  • -d
    --debug

    • 打印调试输出。
  • -D varname = value
    --define= varname = value

    • 定义一个供自定义脚本使用的变量(请参见下文)。允许多个-D选项。
  • -f filename[@weight]
    --file= filename[@weight]

    • 将从* filename *读取的事务脚本添加到已执行脚本的列表中。 @之后的可选整数权重允许调整绘制测试的概率。有关详情,请参见下文。
  • -j threads
    --jobs= threads

    • pgbench 中的工作线程数。在多 CPU 机器上使用多个线程可能会有所帮助。Client 端在可用线程中尽可能均匀地分布。默认值为 1.
  • -l
    --log

    • 将有关每个事务的信息写入日志文件。有关详情,请参见下文。
  • -L limit
    --latency-limit= limit

    • 持续时间超过* limit 毫秒的事务将单独计算并报告为 late *。

使用限制(--rate=...)时,比计划滞后时间多* limit * ms 的事务将因此根本不发送到服务器,因此它们不希望达到延迟限制。它们被计数并分别报告为“已跳过”。

  • -M querymode
    --protocol= querymode

    • 用于向服务器提交查询的协议:
  • simple:使用简单的查询协议。

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

  • prepared:对准备好的语句使用扩展查询协议。

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

  • -n
    --no-vacuum

    • 运行测试之前,请勿抽真空。如果您正在运行不包含标准表pgbench_accountspgbench_branchespgbench_historypgbench_tellers的自定义测试方案,则此选项为[必需]。
  • -N
    --skip-some-updates

    • 运行内置的简单更新脚本。 -b simple-update的简写。
  • -P sec
    --progress= sec

    • 每隔sec *秒显示进度报告。该报告包括自运行开始以来的时间,自上次报告以来的 tps 以及自上次报告以来的事务延迟平均数和标准差。在节流(-R)下,延迟是相对于事务调度的开始时间而不是实际事务开始时间计算的,因此它还包括平均调度滞后时间。
  • -r
    --report-latencies

    • 在基准测试完成后,报告每个命令的平均每个语句延迟(从 Client 端的角度来看,执行时间)。有关详情,请参见下文。
  • -R rate
    --rate= rate

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

通过按照 Poisson 分配的时间表时间线开始 Transaction 来确定汇率。预期的开始时间表是根据 Client 首次启动的时间而不是先前的事务结束的时间而向前移动。这种方法意味着,当 Transaction 超过其原始计划的结束时间时,以后的 Transaction 有可能再次赶上。

当节流处于活动状态时,将根据计划的开始时间计算运行结束时报告的事务延迟,因此它包括每个事务必须 await 上一个事务完成的时间。await 时间称为调度延迟时间,它的平均值和最大值也分别报告。相对于实际事务开始时间的事务 await 时间,即在数据库中执行事务所花费的时间,可以通过从报告的 await 时间中减去调度延迟时间来计算。

如果将--latency-limit--rate一起使用,则事务可能会滞后很多,以至于上一个事务结束时它已经超过了延迟限制,因为延迟是根据计划的开始时间计算的。此类事务不会发送到服务器,但会完全跳过并单独计数。

较高的调度滞后时间表示系统无法使用选定数量的 Client 端和线程以指定的速率处理事务。当平均事务执行时间长于每个事务之间的计划时间间隔时,每个连续事务将进一步落后,并且调度滞后时间将随着测试运行时间的延长而持续增加。发生这种情况时,您将不得不降低指定的 Transaction 率。

  • -s scale_factor
    --scale= scale_factor

    • 在 pgbench 的输出中报告指定的比例因子。对于内置测试,这是没有必要的。通过计算pgbench_branches表中的行数,可以检测到正确的比例因子。但是,当仅测试自定义基准(-f选项)时,除非使用此选项,否则比例因子将报告为 1.
  • -S
    --select-only

    • 运行内置的全选脚本。 -b select-only的简写。
  • -t transactions
    --transactions= transactions

    • 每个 Client 端运行的事务数。默认值是 10.
  • -T seconds
    --time= seconds

    • 运行测试持续这么长时间,而不是每个 Client 端进行固定数量的事务。 -t-T是互斥的。
  • -v
    --vacuum-all

    • 在运行测试之前,先抽真空所有四个标准表。既不使用-n也不使用-v,pgbench 将清理pgbench_tellerspgbench_branches表,并截断pgbench_history
  • --aggregate-interval=seconds

    • 聚合时间间隔的长度(以秒为单位)。只能与-l选项一起使用。使用此选项,日志包含每个时间间隔的摘要数据,如下所述。
  • --log-prefix=prefix

    • --log创建的日志文件设置文件名前缀。默认值为pgbench_log
  • --progress-timestamp

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

    • 将数据写入日志时使用的采样率,以减少生成的日志量。如果指定了此选项,则仅记录指定部分的事务。 1.0 表示将记录所有事务,0.05 表示将仅记录 5%的事务。

在处理日志文件时,请记住要考虑采样率。例如,在计算 tps 值时,您需要相应地将数字相乘(例如,以 0.01 的采样率,您只会得到实际 tps 的 1/100)。

Common Options

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

  • -h hostname
    --host= hostname

    • 数据库服务器的主机名
  • -p port
    --port= port

    • 数据库服务器的端口号
  • -U login
    --username= login

    • 连接的用户名
  • -V
    --version

    • 打印 pgbench 版本并退出。
  • -?
    --help

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

Notes

在 pgbench 中实际执行的“事务”是什么?

pgbench 执行从指定列表中随机选择的测试脚本。它们包括带有-b的内置脚本和带有-f的用户提供的自定义脚本。可以给每个脚本一个@之后指定的相对权重,以更改其绘制概率。默认权重为1。权重为0的脚本将被忽略。

默认的内置事务脚本(也用-b tpcb-like调用)在随机选择的aidtidbiddelta上为每个事务发出七个命令。该方案的灵感来自 TPC-B 基准,但实际上不是 TPC-B,因此得名。

  • 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;

如果您选择simple-update内置(也是-N),则事务中不包含步骤 4 和 5.这样可以避免在这些表上发生更新争用,但是这会使测试用例像 TPC-B 一样少。

如果选择内置的select-only(也为-S),则仅发出SELECT

Custom Scripts

pgbench 通过使用从文件中读取的事务脚本(-f选项)替换默认事务脚本(如上所述)来支持运行自定义基准测试方案。在这种情况下,“事务”被视为脚本文件的一次执行。

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

Note

在 PostgreSQL 9.6 之前,脚本文件中的 SQL 命令以换行符终止,因此不能跨行 continue。现在,“ *”号是必需的,以分隔连续的 SQL 命令(尽管如果 SQL 命令后面跟有 meta 命令,则不需要一个分号)。如果您需要创建一个适用于新旧版本 pgbench 的脚本文件,请确保将每条 SQL 命令写在以分号结尾的一行上。

脚本文件有一个简单的变量替换工具。可以通过上面说明的命令行-D选项或下面说明的 meta 命令来设置变量。除了-D命令行选项预设的任何变量外,还有一些自动预设的变量,列在Table 241中。使用-D为这些变量指定的值优先于自动预设。设置后,可以通过写入: * variablename *将变量的值插入到 SQL 命令中。当运行多个 Client 端会话时,每个会话都有自己的一组变量。

表 241.自动变量

VariableDescription
scale当前比例因子
client_id标识 Client 端会话的唯一编号(从零开始)

脚本文件元命令以反斜杠(\)开头,并且通常延伸到该行的末尾,尽管可以通过编写反斜杠-返回将它们 continue 到其他行。 meta 命令的参数由空格分隔。支持以下 meta 命令:

  • \set varname expression
    • 将变量* varname 设置为从 expression *计算得出的值。该表达式可以包含整数常量(例如5432),双常量(例如3.14159),对变量: * variablename *的引用,一元运算符(+-)和二进制运算符(+-*/%),它们的惯常优先级是关联性function calls和括号。

Examples:

\set ntellers 10 * :scale
\set aid (1021 * random(1, 100000 * :scale)) % \
           (100000 * :scale) + 1
  • \sleep number [ us | ms | s ]

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

Example:

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

    • 将变量* varname 设置为具有给定 argument (s)的 shell 命令 command *的结果。该命令必须通过其标准输出返回一个整数值。
  • command 和每个 argument *可以是文本常量,也可以是对变量的: * variablename 引用。如果要使用以冒号开头的 argument ,请在 argument *的开头写入另一个冒号。

Example:

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

    • \setshell相同,但是命令的结果将被丢弃。

Example:

\shell command literal_argument :variable ::literal_starting_with_colon

Built-In Functions

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

表 242. pgbench 函数

FunctionReturn TypeDescriptionExampleResult
abs(a)与* a *相同absolute valueabs(-17)17
debug(a)与* a *相同打印* a 到 stderr,然后返回 a *debug(5432.1)5432.1
double(i)double投双double(5432)5432.0
greatest(a [, ... ] )如果有任何* a *为 double,则为 double,否则为整数参数中的最大值greatest(5, 4, 3, 2)5
int(x)integer转换为 intint(5.4 + 3.8)9
least(a [, ... ] )如果有任何* a *为 double,则为 double,否则为整数参数中的最小值least(5, 4, 3, 2.1)2.1
pi()double常数 PI 的值pi()3.14159265358979323846
random(lb, ub)integer[lb, ub]中均匀分布的随机整数random(1, 10)110之间的整数
random_exponential(lb, ub, parameter)integer[lb, ub]中的指数分布随机整数,请参见下文random_exponential(1, 10, 3.0)110之间的整数
random_gaussian(lb, ub, parameter)integer[lb, ub]中的高斯分布随机整数,请参见下文random_gaussian(1, 10, 2.5)110之间的整数
sqrt(x)doublesquare rootsqrt(2.0)1.414213562

random函数使用均匀分布生成值,即所有值均以相等的概率绘制在指定范围内。 random_exponentialrandom_gaussian函数需要一个附加的 double 参数,该参数确定分布的精确形状。

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

f(x)= exp(-参数*(x-最小)/(max-最小 1))/(1-exp(-参数))

然后以f(i) - f(i + 1)的概率得出* min max *之间的值i1 *。

直观地,* parameter 越大,访问 min 的值的频率越高,访问 max *的值的频率越低。越接近 0 * parameter ,访问分布越平坦(越均匀)。分布的粗略估计是,在 min 范围内,最接近 1%的值被绘制为 parameter *%的时间。 * parameter *值必须严格为正。

  • 对于高斯分布,间隔被 Map 到标准正态分布(经典的钟形高斯曲线),该正态分布在左侧的-parameter和右侧的+parameter处被截断。间隔中间的值更可能被绘制。确切地说,如果PHI(x)是标准正态分布的累 Integration 布函数,且均值mu定义为(max + min) / 2.0,则

f(x)= PHI(2.0 参数(x-mu)/(max-min 1))/
(2.0 * PHI(参数)-1)

然后以概率f(i + 0.5) - f(i - 0.5)绘制* min max *之间的值i1 。直观地, parameter 越大,绘制到区间中间的值越频繁,而接近 min max 边界的值越少。大约 67%的值来自中间的1.0 / parameter,即平均值附近的相对0.5 / parameter,而 95%的中间值2.0 / parameter则是平均值附近的1.0 / parameter;例如,如果 parameter 为 4.0,则从间隔的中间四分之一(1.0/4.0)(即从3.0 / 8.05.0 / 8.0)中抽取 67%的值,从间隔的中间一半(2.0 / 4.0)中抽取 95%的值(第二和第三个四分位数)。对于 Box-Muller 变换,最小值 parameter *为 2.0.

例如,内置 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;

该脚本允许事务的每次迭代引用不同的随机选择的行。 (此示例还显示了为什么每个 Client 端会话都有自己的变量很重要,否则它们将不会独立地涉及不同的行.)

Per-Transaction Logging

使用-l选项(但不使用--aggregate-interval选项),pgbench 将有关每个事务的信息写入日志文件。日志文件将命名为prefix.nnn,其中* prefix 默认为pgbench_log nnn 是 pgbench 进程的 PID。可以使用--log-prefix选项更改前缀。如果-j选项为 2 或更高,则有多个工作线程,每个工作线程都有自己的日志文件。第一个工作程序将在其日志文件中使用与标准单工作程序情况下相同的名称。其他工作程序的其他日志文件将命名为prefix.nnn.mmm,其中 mmm *是每个工作程序从 1 开始的序号。

日志格式为:

client_id transaction_no time script_no time_epoch time_us [ schedule_lag ]

其中* client_id 指示哪个 Client 端会话运行了该事务, transaction_no 计算该会话已运行了多少个事务, time 是经过的总事务处理时间(以微秒为单位), script_no 标识使用了哪个脚本文件(使用-f-b指定了多个脚本,并且 time_epoch / time_us *是 Unix 时代的时间戳,其偏移量以微秒为单位(适用于创建带有小数秒的 ISO 8601 时间戳),用于显示 Transaction 完成的时间。 * schedule_lag 字段是事务的计划开始时间与实际开始时间之间的差,以微秒为单位。仅在使用--rate选项时存在。当同时使用--rate--latency-limit时,跳过事务的 time *将报告为skipped

这是在单 Client 端运行中生成的日志文件的片段:

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 晚了,因为它的 await 时间(6.173 ms)超过了 5 ms 的限制。接下来的两个事务被跳过,因为它们已经很晚才开始。

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

Aggregated Logging

使用--aggregate-interval选项,日志文件将使用其他格式:

interval_start num_transactions sum_latency sum_latency_2 min_latency max_latency [ sum_lag sum_lag_2 min_lag max_lag [ skipped ] ]

其中* interval_start 是间隔的开始(以 Unix 纪元时间戳记), num_transactions 是间隔内的事务数, sum_latency 是间隔内的事务延迟之和, sum_latency_2 是间隔内事务延迟的平方和, min_latency 是间隔内的最小延迟, max_latency 是间隔内的最大延迟。接下来的字段 sum_lag sum_lag_2 min_lag max_lag 仅在使用--rate选项时出现。它们提供有关每个事务必须 await 上一个事务完成的时间的统计信息,即每个事务的计划开始时间与实际开始时间之间的差额。仅当也使用--latency-limit选项时,才出现最后一个字段 skipped *。它计算因 Transaction 开始得太晚而跳过的 Transaction 数量。每个事务在提交后的时间间隔中进行计数。

这是一些示例输出:

1345828501 5601 1542744 483552416 61 2573
1345828503 7884 1979812 565806736 60 1479
1345828505 7208 1979422 567277552 59 1391
1345828507 7685 1980268 569784714 60 1398
1345828509 7073 1979779 573489941 236 1411

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

Per-Statement Latencies

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

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

starting vacuum...end.
transaction type: <builtin: 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
latency average = 15.844 ms
latency stddev = 2.715 ms
tps = 618.764555 (including connections establishing)
tps = 622.977698 (excluding connections establishing)
script statistics:
 - statement latencies in milliseconds:
        0.002  \set aid random(1, 100000 * :scale)
        0.005  \set bid random(1, 1 * :scale)
        0.002  \set tid random(1, 10 * :scale)
        0.001  \set delta random(-5000, 5000)
        0.326  BEGIN;
        0.603  UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
        0.454  SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
        5.528  UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
        7.335  UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
        0.371  INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
        1.212  END;

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

请注意,收集每个语句 await 时间计算所需的其他时序信息会增加一些开销。这将降低平均执行速度并降低计算的 TPS。减速的程度因平台和硬件而异。比较启用和未启用延迟报告的平均 TPS 值是衡量计时开销是否重大的一种好方法。

Good Practices

使用 pgbench 产生完全没有意义的数字非常容易。以下是一些指南,可帮助您获得有用的结果。

首先,永远不要相信任何运行仅几秒钟的测试。使用-t-T选项可以使运行至少持续几分钟,以平均噪音。在某些情况下,您可能需要几个小时才能获得可重现的数字。尝试运行几次测试是一个好主意,以查明您的数字是否可重复。

对于默认的类似 TPC-B 的测试方案,初始化比例因子(-s)至少应与要测试的最大 Client 端数量(-c)一样大。否则,您将主要衡量更新争用。 pgbench_branches表中只有-s行,并且每个事务都想要更新其中之一,因此-c值超过-s无疑会导致许多事务被阻塞,以 await 其他事务。

默认的测试方案对于初始化表以来已经有多长时间非常敏感:死行和死空间的累积会改变结果。要了解结果,您必须跟踪更新的总数以及清理发生的时间。如果启用了自动真空,则可能会导致测量性能发生不可预测的变化。

pgbench 的局限性在于,它在尝试测试大量 Client 端会话时本身可能成为瓶颈。可以通过在与数据库服务器不同的机器上运行 pgbench 来缓解这种情况,尽管低网络延迟是必不可少的。在多台 Client 端计算机上针对同一数据库服务器同时运行多个 pgbench 实例甚至可能很有用。

Security

如果不受信任的用户可以访问未采用安全模式使用模式的数据库,则不要在该数据库中运行 pgbench。 pgbench 使用非限定名称,并且不操纵搜索路径。