0
点赞
收藏
分享

微信扫一扫

PostgreSQL 新版本就一定好--由培训现象让我做的实验

PostgreSQL的版本推进的很快,目前已经到了PG18的非正式版本研发的状态。基于一些数据库产品在推进时容易出现的一些问题,比如新版本的性能在某些方面还不如老的版本这个问题。

我们将展开一个新的PostgreSQL的系列,从相近的版本去发现版本是否存在差异,来从版本的差异上去寻找一些问题。

找差异的方法有很多,我们就从最直接的方式来,我们准备了,两台同样的虚拟机,同样的配置,且虚拟机在同一台物理机上。同样去安装 POSTGRESQL 16.8 和 POSTGRESQL 17.4,用同样的方式去编译数据库,同样的参数。同样的压测的方法。我们来进行数据的采集,最终我们获得版本的差异为我们带来的不同。

一、数据的插入的性能差异。

数据的输入时的性能差异是很多数据库系统在一直优化,且努力让数据写入的速率的,这里我们通过基本pg_bench 来进行简易的测试,在同样配置的数据库中,插入1000万数据,我们来看差距是否存在。我们同样的事情至少做三遍并且我们会将数据列出来。

Initialization started at: 2025-06-02 06:47:53
[postgres@postgresql16 ~]$ pgbench -i -s 100 -U postgres -d my_pgbench_db
dropping old tables...
creating tables...
generating data (client-side)...
2025-06-02 06:48:00.362 CST [10778] LOG:  checkpoint starting: wal.89 s)
10000000 of 10000000 tuples (100%) done (elapsed 7.08 s, remaining 0.00 s)
vacuuming...
creating primary keys...
donein 10.31 s (drop tables 0.06 s, create tables 0.06 s, client-side generate 7.32 s, vacuum 0.17 s, primary keys 2.71 s).
[postgres@postgresql16 ~]$ echo"Initialization finished at: $(date '+%Y-%m-%d %H:%M:%S')"
Initialization finished at: 2025-06-02 06:48:03
[postgres@postgresql16 ~]$ echo"end"

[postgres@postgresql17 ~]$ echo "Initialization started at: $(date '+%Y-%m-%d %H:%M:%S')"
Initialization started at: 2025-06-01 10:47:16
[postgres@postgresql17 ~]$ pgbench -i -s 100 -U postgres -d my_pgbench_db
dropping old tables...
creating tables...
generating data (client-side)...
vacuuming...                                                                                  
creating primary keys...
donein 6.86 s (drop tables 0.05 s, create tables 0.00 s, client-side generate 4.96 s, vacuum 0.16 s, primary keys 1.69 s).
[postgres@postgresql17 ~]$ echo"Initialization finished at: $(date '+%Y-%m-%d %H:%M:%S')"
Initialization finished at: 2025-06-01 10:47:23
[postgres@postgresql17 ~]$ echo"end"

测试编号

数据量 (万条)

完成时间

版本

1

1000

4.46S

16

2

1000

4.48S

16

3

1000

6.63S

16

4

1000

4.66S

17

6

1000

4.59S

17

7

1000

4.96S

17

除此以外我们还进行了普通的测试,其中包含了客户端从10到50的逐渐数据的查询和DML的操作,下面我们将给出相关的测试脚本和过程。

[postgres@postgresql17 ~]$ bash test.sh
测试结果将保存到: pgbench_results_20250601_120531
---------------------------------------------------------
## 正在运行客户端数量为: 10 的测试 ##
开始时间: 2025-06-01 12:05:31
---------------------------------------------------------
## pgbench 命令执行失败,客户端数量为: 10 ##
请检查错误信息,日志文件: pgbench_results_20250601_120531/pgbench_c10_t30.log
暂停 5 秒,然后继续下一个客户端数量...
## 正在运行客户端数量为: 20 的测试 ##
开始时间: 2025-06-01 12:05:36
---------------------------------------------------------
## pgbench 命令执行失败,客户端数量为: 20 ##
请检查错误信息,日志文件: pgbench_results_20250601_120531/pgbench_c20_t30.log
暂停 5 秒,然后继续下一个客户端数量...
## 正在运行客户端数量为: 30 的测试 ##
开始时间: 2025-06-01 12:05:41
---------------------------------------------------------
## pgbench 命令执行失败,客户端数量为: 30 ##
请检查错误信息,日志文件: pgbench_results_20250601_120531/pgbench_c30_t30.log
暂停 5 秒,然后继续下一个客户端数量...
## 正在运行客户端数量为: 40 的测试 ##
开始时间: 2025-06-01 12:05:46
---------------------------------------------------------
## pgbench 命令执行失败,客户端数量为: 40 ##
请检查错误信息,日志文件: pgbench_results_20250601_120531/pgbench_c40_t30.log
暂停 5 秒,然后继续下一个客户端数量...
## 正在运行客户端数量为: 50 的测试 ##
开始时间: 2025-06-01 12:05:51
---------------------------------------------------------
## pgbench 命令执行失败,客户端数量为: 50 ##
请检查错误信息,日志文件: pgbench_results_20250601_120531/pgbench_c50_t30.log
所有测试阶段完成!
所有详细结果文件位于: pgbench_results_20250601_120531

#!/bin/bash

# --- 配置参数 ---
DB_USER="postgres"               # 数据库用户
DB_NAME="my_pgbench_db"          # 数据库名
PGBENCH_SCRIPT="custom_mixed.sql"# pgbench 脚本文件
SCALE_FACTOR=100                 # 数据缩放因子 (与初始化时保持一致,确保脚本变量正确)
THREADS=8                        # 每个pgbench实例使用的线程数 (通常设置为CPU核心数)
DURATION=30                      # 每个测试阶段的运行时间 (秒)
PROGRESS_REPORT=5                # 每隔多少秒打印一次进度报告
START_CLIENTS=10                 # 起始客户端数量
END_CLIENTS=50                   # 结束客户端数量
CLIENT_STEP=10                   # 每次增加的客户端步长
PAUSE_SECONDS=5                  # 每个测试阶段之间暂停的秒数

OUTPUT_DIR="pgbench_results_$(date +%Y%m%d_%H%M%S)"# 结果输出目录

# --- 函数:打印分隔线 ---
print_separator() {
    echo"---------------------------------------------------------"
}

# --- 创建结果输出目录 ---
mkdir -p "$OUTPUT_DIR"
echo"测试结果将保存到: $OUTPUT_DIR"
print_separator

# --- 循环执行 pgbench ---
for clients in $(seq $START_CLIENTS$CLIENT_STEP$END_CLIENTS)
do
    echo"## 正在运行客户端数量为: $clients 的测试 ##"
    echo"开始时间: $(date '+%Y-%m-%d %H:%M:%S')"
    print_separator

    OUTPUT_FILE="${OUTPUT_DIR}/pgbench_c${clients}_t${DURATION}.log"

    pgbench -f "$PGBENCH_SCRIPT" \
            -c "$clients" \
            -j "$THREADS" \
            -T "$DURATION" \
            -r \
            -P "$PROGRESS_REPORT" \
            -U "$DB_USER" \
            -d "$DB_NAME" \
            -s "$SCALE_FACTOR" \
            > "$OUTPUT_FILE" 2>&1 # 将所有输出重定向到文件

    EXIT_CODE=$?
    if [ $EXIT_CODE -ne 0 ]; then
        echo"## pgbench 命令执行失败,客户端数量为: $clients ##" | tee -a "$OUTPUT_FILE"
        echo"请检查错误信息,日志文件: $OUTPUT_FILE"
    else
        echo"## 客户端数量为: $clients 的测试完成 ##"
        echo"结束时间: $(date '+%Y-%m-%d %H:%M:%S')"
        echo"结果已保存到: $OUTPUT_FILE"
        print_separator
        # 打印关键摘要到控制台
        echo"摘要 (客户端: $clients):"
        grep "tps =""$OUTPUT_FILE" | head -n 1
        grep "latency average =""$OUTPUT_FILE"
        print_separator
    fi

    if [ "$clients" -lt "$END_CLIENTS" ]; then
        echo"暂停 ${PAUSE_SECONDS} 秒,然后继续下一个客户端数量..."
        sleep "$PAUSE_SECONDS"
    fi
done

echo"所有测试阶段完成!"
echo"所有详细结果文件位于: $OUTPUT_DIR"

-- custom_mixed.sql
`
-- 联合查询和写入的 pgbench 脚本

-- 随机选择一个账户ID,范围是 1 到 (scale_factor * 100000)
-- 假设 scale_factor = 10,则 aid 范围是 1 到 10000000

\set scale_factor 100
\set aid random(1, :scale_factor * 100000)
\set bid random(1, :scale_factor * 1)
\set tid random(1, :scale_factor * 10)
\set delta random(-5000, 5000)
-- 随机的金额变动 (注释移动到单独一行,或者删除)

BEGIN;

-- 查询操作 1: 查询特定账户的余额
SELECT abalance FROM pgbench_accounts WHERE aid = :aid;

-- 写入操作 1: 更新账户余额
UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;

-- 写入操作 2: 更新出纳员余额
UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;

-- 写入操作 3: 更新分支余额
UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;

-- 写入操作 4: 插入历史记录
INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, now());

-- 查询操作 2: 联合查询一些数据(例如,从账户表和出纳员表联合查询)
SELECT a.aid, a.abalance, t.tbalance
FROM pgbench_accounts a, pgbench_tellers t
WHERE a.aid = :aid AND t.tid = :tid;

COMMIT;

测试批次

客户端数量 (C)

线程数 (J)

持续时间 (秒)

事务总数

失败事务数

平均延迟 (ms)

延迟标准差 (ms)

TPS (每秒事务数)

备注

17

10

8

30S

12993

0

14.975 ms

629.864 ms

667.573826

17

20

8

30S

20589

0

38.841 ms

962.272 ms

514.764547

17

30

8

30S

10505

0

87.947 ms

1308.477 ms

341.008574

17

40

8

30S

20872

0

107.095 ms

1529.057 m

90.696109

17

50

8

30S

24726

0

66.365 ms

1278.599 ms

752.918106

16

10

8

30S

109111

0

2.636 ms

508.185 ms

3634.577691

16

20

8

30S

120542

0

4.748

1.078 ms

4013.857067

16

30

8

30S

123626

0

6.881 ms

3.400 ms

4116.228912

16

40

8

30S

125420

0

8.981 ms

8.981 ms

4175.357838

16

50

8

30S

128547

0

10.915 ms

10.915 ms

4279.730086

PostgreSQL 新版本就一定好--由培训现象让我做的实验_客户端


特殊的情况截图

从数据上看,PG17 PG16 各有自己的特点,但PG16的数据出奇的比PG17的好,我在测试的时候认为是突发情况,就对PG16的数据库又进行了4次测试,对PG17进行了同样的3次此时,最终我不得不把上面的数据呈现出来。

这也是我一直担心的一个问题,新版本的性能比老版本的性能低。出现这个问题在数据库业界并不是少数派事件,在某开源数据库的共识是新的版本的性能逐渐下降对比之前5.7的性能8.0的性能在一些简单的操作上更慢了。

所以这次我也对PG进行了测试没想到得出的结果也让我...... ,同时我也想提醒一件事,也是最近一个培训课上一些同学经常问我的问题,为什么不讲最新的版本。

我的解释是

1  培训大纲的要求 

2  新版本未必比旧版本在实用性上强 

3  一些同学盲目求新,新版本和旧版本的一些知识体系又了改变,则课上不会在讲之前的一些坑,因为新版本上解决了老版本的问题,这点尤其在PG上非常突出。教学的任务可能对我来说更轻松了,但如果你去的单位用的是老版本,那么你不进行体系化的对老版本的熟悉,你讲无法处理新版本已经不出现,老版本依然是问题的问题。

这也是我这篇文章想说的,数据库相对运维来说更严谨,新版本固然好,但是完全好吗,自己思索思索。


PostgreSQL 新版本就一定好--由培训现象让我做的实验_数据库_02


新版本一定好?

举报

相关推荐

0 条评论