测算查询 PostgreSQL 时的 CPU 指令数

John Doe 一月 12, 2026

摘要:Michael Stonebraker 曾经发表过一篇经典论文:OLTP 的镜中奇遇与发现之旅。其中以指令数为指标,统计数据库各个阶段的负载。

目录

PostgreSQL 处理器指令数测试

1. 下面我们在 PostgreSQL 的数据库中,创建一个表,插入一些数据,并对表数据进行清理和分析。

CREATE TABLE t_large (id integer, name text);

INSERT INTO t_large (id, name)
  SELECT i, repeat('Pg', 16)
    FROM generate_series(1, 1000000) AS s(i);

CREATE INDEX large_idx ON t_large (id);
VACUUM ANALYZE t_large;

2. 在准备好基础表和初始数据后,让我们查询下当前会话的后端进程 ID:

SELECT pg_backend_pid();
 pg_backend_pid
----------------
          22328
(1 row)

3. 在 Linux 命令行交互窗口中,使用 perf 打开 CPU 指令数计数器,针对进程 22328,统计它执行的指令数:

$ perf stat -einstructions:u -p 22328

注意:上面的命令中,“instructions:u” 中的 “:u”,是只统计用户态执行的指令数。我们排除于内核态的指令,去除一些干扰,统计结果更精准。

4. 回到前面的数据库会话中,执行目标 SQL:

SELECT * FROM t_large WHERE id = 202601;

5. 回到前面的 perf 命令窗口,执行Ctrl+C,就能看到结果了:

$ perf stat -einstructions:u -p 22328
^C
 Performance counter stats for process id '22328':

           440,708      instructions:u

       6.691347285 seconds time elapsed

重复上面的步骤 3 到 5,再次观察测试结果:

$ perf stat -einstructions:u -p 22328
^C
 Performance counter stats for process id '22328':

           253,770      instructions:u

       5.804768145 seconds time elapsed

Redrock Postgres 处理器指令数测试

1. 下面我们在 Redrock Postgres 的数据库中,创建一个表,插入一些数据,并对表数据进行清理和分析。

CREATE TABLE t_large (id integer, name text);

INSERT INTO t_large (id, name)
  SELECT i, repeat('Pg', 16)
    FROM generate_series(1, 1000000) AS s(i);

CREATE INDEX large_idx ON t_large (id);
VACUUM ANALYZE t_large;

2. 在准备好基础表和初始数据后,让我们查询下当前会话的后端进程 ID:

SELECT pg_backend_pid();
 pg_backend_pid
----------------
          23030
(1 row)

3. 在 Linux 命令行交互窗口中,使用 perf 打开 CPU 指令数计数器,针对进程 23030,统计它执行的指令数:

$ perf stat -einstructions:u -p 23030

4. 回到前面的数据库会话中,执行目标 SQL:

SELECT * FROM t_large WHERE id = 202601;

5. 回到前面的 perf 命令窗口,执行Ctrl+C,就能看到结果了:

$ perf stat -einstructions:u -p 23030
^C
 Performance counter stats for process id '23030':

           468,431      instructions:u

       6.048133731 seconds time elapsed

重复上面的步骤 3 到 5,再次观察测试结果:

$ perf stat -einstructions:u -p 23030
^C
 Performance counter stats for process id '23030':

           237,542      instructions:u

       6.472907115 seconds time elapsed

测试结果对比

汇总对比上面的测试结果,如下:

PostgreSQL Redrock Postgres 提升率
首次查询 440,708 468,431 -6.3%
二次查询 253,770 237,542 6.4%

另外,我们最近改进了启用数据校验和情况下的查询性能,下面是基于开发版本的测试结果(启用数据校验和):

PostgreSQL Redrock Postgres 提升率
首次查询 545,638 517,284 5.2%
二次查询 265,435 249,524 6%

该改进将会体现在 Redrock Postgres 的下一个版本中。

注意:PostgreSQL 18 更改了 initdb 的默认设置,启用了数据校验和(data checksums)。