postgres--性能,压力测试

测试 PostgreSQL 和 MySQL 通常围绕功能正确性、性能、稳定性和安全性展开。以下是核心的测试方法、常用工具和关键步骤。

一、连接与基础功能测试

这是最基本的测试,确保应用能正常连接和操作数据库。

  1. 使用命令行客户端或GUI工具连接

    • PostgreSQL : 使用 psql 命令行或 pgAdmin、DBeaver 等工具。

      bash 复制代码
      psql -h 主机名 -p 端口 -U 用户名 -d 数据库名
    • MySQL : 使用 mysql 命令行或 MySQL Workbench、Navicat 等工具。

      bash 复制代码
      mysql -h 主机名 -P 端口 -u 用户名 -p 数据库名
  2. 执行基本CRUD操作

    • 创建表、插入数据、查询、更新、删除,验证SQL语法兼容性和执行结果是否符合预期。
    • 测试事务(BEGIN, COMMIT, ROLLBACK)是否正常工作。

二、性能测试(压测)

这是评估数据库处理能力的关键,尤其与您之前设置的连接池参数直接相关。

  1. 常用压测工具

    数据库 推荐工具 主要用途
    PostgreSQL pgbench (内置) 标准的TPC-B-like基准测试,测试综合事务处理能力。
    MySQL sysbench 支持CPU、内存、文件I/O、数据库OLTP等多种测试。
    两者均可 HammerDB (图形化) 支持TPC-C, TPC-H等更复杂的商业负载测试。
    两者均可 自定义脚本 (如用Go/Python编写) 模拟最真实的业务查询逻辑进行压测。
  2. 关键性能指标

    • 吞吐量:QPS(每秒查询数)、TPS(每秒事务数)。
    • 延迟:平均响应时间、P95/P99分位响应时间。
    • 资源利用率:数据库服务器的CPU、内存、磁盘I/O、网络I/O使用率。
    • 连接与错误:当前连接数、连接错误数、慢查询数量。
  3. 一个简单的压测示例

    • PostgreSQL (使用 pgbench) :

      bash 复制代码
      # 1. 初始化测试数据(例如,在"test_db"中创建4张表,缩放因子为100)
      pgbench -h localhost -U postgres -i -s 100 test_db
      # 2. 运行压测:10个客户端,并发运行60秒
      pgbench -h localhost -U postgres -c 10 -j 2 -T 60 test_db
    • MySQL (使用 sysbench) :

      bash 复制代码
      # 1. 准备数据(例如,创建10张表,每张表10万行)
      sysbench oltp_read_write --db-driver=mysql --mysql-host=localhost \
        --mysql-user=root --mysql-password=your_password --mysql-db=sbtest \
        --table-size=100000 --tables=10 prepare
      # 2. 运行压测:8个线程,运行300秒
      sysbench oltp_read_write --db-driver=mysql --mysql-host=localhost \
        --mysql-user=root --mysql-password=your_password --mysql-db=sbtest \
        --threads=8 --time=300 run

三、稳定性与可靠性测试

  1. 长时间压力测试:使用上述压测工具,以稳定的压力运行数小时甚至数天,观察性能曲线是否平稳,内存是否有泄漏。
  2. 故障恢复测试
    • 网络闪断:模拟网络中断后,连接池是否能正确重连。
    • 数据库重启:重启数据库服务,验证应用是否能自动恢复连接并继续工作。
    • 主从切换(如果使用了复制):模拟主库故障,验证备库能否顺利提升为主库,应用能否切换到新主库。

四、安全性测试

  1. 权限测试:使用不同权限的账户登录,验证其是否只能执行被授权的操作。
  2. SQL注入测试:使用工具(如 sqlmap)或手动构造异常输入,测试应用层是否有效防范了SQL注入。
  3. 网络与加密:测试是否强制使用了SSL/TLS加密连接。

五、监控与日志分析

在测试过程中和上线后,持续监控至关重要。

  • PostgreSQL : 监控 pg_stat_activity(当前活动)、pg_stat_statements(SQL统计),分析日志中的错误和慢查询。
  • MySQL : 监控 SHOW PROCESSLIST(当前连接)、performance_schemasys 库,分析慢查询日志 (slow_query_log) 和错误日志。

总结与建议

  1. 明确测试目标:是验证功能、寻找性能瓶颈,还是测试高可用方案?
  2. 模拟真实负载 :尽可能使用贴近业务的SQL进行测试,pgbenchsysbench的默认模板只是一个起点。
  3. 从测试环境开始切勿在生产数据库上直接进行压测。先在配置相似的测试环境进行。
  4. 循序渐进:从小并发开始,逐步增加压力,观察各项指标的变化趋势,找到性能拐点。
  5. 结合应用测试:最真实的测试是使用您的应用程序,配合APM工具进行全链路压测。

通过以上方法的组合,您可以全面评估PostgreSQL或MySQL数据库的健壮性和性能表现,并为优化配置(如您之前关心的最大连接数)提供数据支持。

pgbench 运行结果解读

运行 pgbench -h localhost -U postgres -i -s 100 test_db 的输出解读如下:

输出示例与解读

bash 复制代码
/ # pgbench -h localhost -U postgres -i -s 100 my_test
dropping old tables...
NOTICE:  table "pgbench_accounts" does not exist, skipping
NOTICE:  table "pgbench_branches" does not exist, skipping
NOTICE:  table "pgbench_history" does not exist, skipping
NOTICE:  table "pgbench_tellers" does not exist, skipping
creating tables...
generating data...
100000 of 10000000 tuples (1%) done (elapsed 0.21 s, remaining 20.67 s)
200000 of 10000000 tuples (2%) done (elapsed 0.43 s, remaining 20.88 s)
300000 of 10000000 tuples (3%) done (elapsed 0.67 s, remaining 21.53 s)
400000 of 10000000 tuples (4%) done (elapsed 1.04 s, remaining 24.99 s)
500000 of 10000000 tuples (5%) done (elapsed 4.92 s, remaining 93.43 s)
600000 of 10000000 tuples (6%) done (elapsed 6.87 s, remaining 107.68 s)
700000 of 10000000 tuples (7%) done (elapsed 8.55 s, remaining 113.62 s)
800000 of 10000000 tuples (8%) done (elapsed 10.40 s, remaining 119.58 s)
900000 of 10000000 tuples (9%) done (elapsed 13.97 s, remaining 141.29 s)
1000000 of 10000000 tuples (10%) done (elapsed 15.77 s, remaining 141.93 s)
1100000 of 10000000 tuples (11%) done (elapsed 17.34 s, remaining 140.31 s)
1200000 of 10000000 tuples (12%) done (elapsed 20.19 s, remaining 148.03 s)
1300000 of 10000000 tuples (13%) done (elapsed 22.17 s, remaining 148.38 s)
1400000 of 10000000 tuples (14%) done (elapsed 24.76 s, remaining 152.07 s)
1500000 of 10000000 tuples (15%) done (elapsed 26.15 s, remaining 148.18 s)
1600000 of 10000000 tuples (16%) done (elapsed 27.70 s, remaining 145.42 s)
1700000 of 10000000 tuples (17%) done (elapsed 29.13 s, remaining 142.21 s)
1800000 of 10000000 tuples (18%) done (elapsed 31.50 s, remaining 143.50 s)
1900000 of 10000000 tuples (19%) done (elapsed 32.83 s, remaining 139.96 s)
2000000 of 10000000 tuples (20%) done (elapsed 34.88 s, remaining 139.53 s)
2100000 of 10000000 tuples (21%) done (elapsed 36.45 s, remaining 137.10 s)
2200000 of 10000000 tuples (22%) done (elapsed 39.91 s, remaining 141.50 s)
2300000 of 10000000 tuples (23%) done (elapsed 41.97 s, remaining 140.52 s)
2400000 of 10000000 tuples (24%) done (elapsed 44.01 s, remaining 139.35 s)
2500000 of 10000000 tuples (25%) done (elapsed 45.55 s, remaining 136.65 s)
2600000 of 10000000 tuples (26%) done (elapsed 48.12 s, remaining 136.95 s)
2700000 of 10000000 tuples (27%) done (elapsed 49.53 s, remaining 133.92 s)
2800000 of 10000000 tuples (28%) done (elapsed 51.24 s, remaining 131.77 s)
2900000 of 10000000 tuples (29%) done (elapsed 53.99 s, remaining 132.19 s)
3000000 of 10000000 tuples (30%) done (elapsed 58.19 s, remaining 135.77 s)
3100000 of 10000000 tuples (31%) done (elapsed 60.58 s, remaining 134.83 s)
3200000 of 10000000 tuples (32%) done (elapsed 67.08 s, remaining 142.54 s)
3300000 of 10000000 tuples (33%) done (elapsed 70.47 s, remaining 143.07 s)
3400000 of 10000000 tuples (34%) done (elapsed 75.49 s, remaining 146.54 s)
3500000 of 10000000 tuples (35%) done (elapsed 77.43 s, remaining 143.79 s)
3600000 of 10000000 tuples (36%) done (elapsed 80.40 s, remaining 142.93 s)
3700000 of 10000000 tuples (37%) done (elapsed 82.06 s, remaining 139.72 s)
3800000 of 10000000 tuples (38%) done (elapsed 83.43 s, remaining 136.13 s)
3900000 of 10000000 tuples (39%) done (elapsed 85.26 s, remaining 133.36 s)
4000000 of 10000000 tuples (40%) done (elapsed 88.07 s, remaining 132.11 s)
4100000 of 10000000 tuples (41%) done (elapsed 92.13 s, remaining 132.58 s)
4200000 of 10000000 tuples (42%) done (elapsed 95.45 s, remaining 131.81 s)
4300000 of 10000000 tuples (43%) done (elapsed 99.59 s, remaining 132.01 s)
4400000 of 10000000 tuples (44%) done (elapsed 105.94 s, remaining 134.83 s)
4500000 of 10000000 tuples (45%) done (elapsed 109.89 s, remaining 134.30 s)
4600000 of 10000000 tuples (46%) done (elapsed 111.46 s, remaining 130.84 s)
4700000 of 10000000 tuples (47%) done (elapsed 113.35 s, remaining 127.83 s)
4800000 of 10000000 tuples (48%) done (elapsed 116.31 s, remaining 126.01 s)
4900000 of 10000000 tuples (49%) done (elapsed 118.10 s, remaining 122.92 s)
5000000 of 10000000 tuples (50%) done (elapsed 119.98 s, remaining 119.98 s)
5100000 of 10000000 tuples (51%) done (elapsed 121.57 s, remaining 116.81 s)
5200000 of 10000000 tuples (52%) done (elapsed 123.40 s, remaining 113.91 s)
5300000 of 10000000 tuples (53%) done (elapsed 126.36 s, remaining 112.06 s)
5400000 of 10000000 tuples (54%) done (elapsed 128.37 s, remaining 109.36 s)
5500000 of 10000000 tuples (55%) done (elapsed 130.19 s, remaining 106.52 s)
5600000 of 10000000 tuples (56%) done (elapsed 131.80 s, remaining 103.56 s)
5700000 of 10000000 tuples (57%) done (elapsed 134.26 s, remaining 101.28 s)
5800000 of 10000000 tuples (58%) done (elapsed 135.48 s, remaining 98.11 s)
5900000 of 10000000 tuples (59%) done (elapsed 136.87 s, remaining 95.11 s)
6000000 of 10000000 tuples (60%) done (elapsed 138.48 s, remaining 92.32 s)
6100000 of 10000000 tuples (61%) done (elapsed 141.00 s, remaining 90.15 s)
6200000 of 10000000 tuples (62%) done (elapsed 142.41 s, remaining 87.28 s)
6300000 of 10000000 tuples (63%) done (elapsed 143.84 s, remaining 84.48 s)
6400000 of 10000000 tuples (64%) done (elapsed 145.39 s, remaining 81.78 s)
6500000 of 10000000 tuples (65%) done (elapsed 147.85 s, remaining 79.61 s)
6600000 of 10000000 tuples (66%) done (elapsed 149.26 s, remaining 76.89 s)
6700000 of 10000000 tuples (67%) done (elapsed 150.64 s, remaining 74.20 s)
6800000 of 10000000 tuples (68%) done (elapsed 152.30 s, remaining 71.67 s)
6900000 of 10000000 tuples (69%) done (elapsed 154.69 s, remaining 69.50 s)
7000000 of 10000000 tuples (70%) done (elapsed 155.95 s, remaining 66.84 s)
7100000 of 10000000 tuples (71%) done (elapsed 157.36 s, remaining 64.27 s)
7200000 of 10000000 tuples (72%) done (elapsed 158.85 s, remaining 61.77 s)
7300000 of 10000000 tuples (73%) done (elapsed 161.28 s, remaining 59.65 s)
7400000 of 10000000 tuples (74%) done (elapsed 162.61 s, remaining 57.13 s)
7500000 of 10000000 tuples (75%) done (elapsed 163.96 s, remaining 54.65 s)
7600000 of 10000000 tuples (76%) done (elapsed 165.58 s, remaining 52.29 s)
7700000 of 10000000 tuples (77%) done (elapsed 168.00 s, remaining 50.18 s)
7800000 of 10000000 tuples (78%) done (elapsed 169.42 s, remaining 47.79 s)
7900000 of 10000000 tuples (79%) done (elapsed 170.83 s, remaining 45.41 s)
8000000 of 10000000 tuples (80%) done (elapsed 172.34 s, remaining 43.09 s)
8100000 of 10000000 tuples (81%) done (elapsed 174.75 s, remaining 40.99 s)
8200000 of 10000000 tuples (82%) done (elapsed 176.11 s, remaining 38.66 s)
8300000 of 10000000 tuples (83%) done (elapsed 177.46 s, remaining 36.35 s)
8400000 of 10000000 tuples (84%) done (elapsed 179.02 s, remaining 34.10 s)
8500000 of 10000000 tuples (85%) done (elapsed 180.33 s, remaining 31.82 s)
8600000 of 10000000 tuples (86%) done (elapsed 182.78 s, remaining 29.75 s)
8700000 of 10000000 tuples (87%) done (elapsed 184.13 s, remaining 27.51 s)
8800000 of 10000000 tuples (88%) done (elapsed 185.68 s, remaining 25.32 s)
8900000 of 10000000 tuples (89%) done (elapsed 186.91 s, remaining 23.10 s)
9000000 of 10000000 tuples (90%) done (elapsed 189.42 s, remaining 21.05 s)
9100000 of 10000000 tuples (91%) done (elapsed 190.84 s, remaining 18.87 s)
9200000 of 10000000 tuples (92%) done (elapsed 192.48 s, remaining 16.74 s)
9300000 of 10000000 tuples (93%) done (elapsed 193.78 s, remaining 14.59 s)
9400000 of 10000000 tuples (94%) done (elapsed 196.32 s, remaining 12.53 s)
9500000 of 10000000 tuples (95%) done (elapsed 197.77 s, remaining 10.41 s)
9600000 of 10000000 tuples (96%) done (elapsed 199.26 s, remaining 8.30 s)
9700000 of 10000000 tuples (97%) done (elapsed 200.63 s, remaining 6.21 s)
9800000 of 10000000 tuples (98%) done (elapsed 203.02 s, remaining 4.14 s)
9900000 of 10000000 tuples (99%) done (elapsed 204.15 s, remaining 2.06 s)
10000000 of 10000000 tuples (100%) done (elapsed 205.41 s, remaining 0.00 s)
vacuuming...
creating primary keys...
done.
/ # pgbench -h localhost -U postgres -c 10 -j 2 -T 60;
ERROR:  relation "pgbench_branches" does not exist
LINE 1: select count(*) from pgbench_branches
                             ^
Perhaps you need to do initialization ("pgbench -i") in database "postgres"
/ # pgbench -h localhost -U postgres -c 10 -j 2 -T 60 my_test;
starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 100
query mode: simple
number of clients: 10
number of threads: 2
duration: 60 s
number of transactions actually processed: 77566
latency average = 7.736 ms
tps = 1292.666229 (including connections establishing)
tps = 1293.665486 (excluding connections establishing)
/ # pgbench -h localhost -U postgres -c 30 -j 2 -T 60 my_test;
starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 100
query mode: simple
number of clients: 30
number of threads: 2
duration: 60 s
number of transactions actually processed: 102295
latency average = 17.612 ms
tps = 1703.401411 (including connections establishing)
tps = 1704.796423 (excluding connections establishing)
/ # pgbench -h localhost -U postgres -c 1000 -j 2 -T 60 my_test;
starting vacuum...end.
connection to database "my_test" failed:
FATAL:  sorry, too many clients already
connection to database "my_test" failed:
FATAL:  sorry, too many clients already
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 100
query mode: simple
number of clients: 1000
number of threads: 2
duration: 60 s
number of transactions actually processed: 0
/ # pgbench -h localhost -U postgres -c 100 -j 2 -T 60 my_test;
starting vacuum...end.
connection to database "my_test" failed:
FATAL:  sorry, too many clients already
^C
/ # pgbench -h localhost -U postgres -c 90 -j 2 -T 60 my_test;
starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 100
query mode: simple
number of clients: 90
number of threads: 2
duration: 60 s
number of transactions actually processed: 64460
latency average = 84.313 ms
tps = 1067.455244 (including connections establishing)
tps = 1068.277856 (excluding connections establishing)
/ # 

详细解读

1. 初始化步骤分解

输出行 含义解析 数据量计算 (缩放因子 s=100)
dropping old tables... 尝试删除可能存在的旧测试表 -
4个 NOTICE: table "xxx" does not exist, skipping 表不存在(正常情况,第一次初始化) -
creating tables... 创建4个标准表结构 -
creating 100 branches... pgbench_branches 表中插入100行 branches = s = 100
creating 1000 tellers... pgbench_tellers 表中插入1000行 tellers = 10 × s = 1000
creating 10000000 accounts in pgbench_accounts... pgbench_accounts 表中插入1000万行 accounts = 100,000 × s = 10,000,000
vacuum... 执行VACUUM操作,清理和优化表 -
set primary keys... 设置主键约束 -
done. 初始化完成 -

2. 表结构说明

初始化后创建4个表:

  1. pgbench_accounts (最大的表)

    • 行数:100,000 × 缩放因子 = 10,000,000 行
    • 每行约200字节
    • 估算大小:~2 GB
    • 主键:aid (account ID)
  2. pgbench_branches

    • 行数:1 × 缩放因子 = 100 行
    • 主键:bid (branch ID)
  3. pgbench_tellers

    • 行数:10 × 缩放因子 = 1,000 行
    • 主键:tid (teller ID)
  4. pgbench_history

    • 初始化时为0行,在压测运行时会插入数据
    • 无主键,只有索引

3. 数据量估算

bash 复制代码
# 根据缩放因子 s=100 估算
- 总行数 ≈ 100 (branches) + 1,000 (tellers) + 10,000,000 (accounts) = 10,000,100 行
- 磁盘空间 ≈ 2-3 GB(取决于你的PostgreSQL版本和配置)
- 索引大小 ≈ 0.5-1 GB

4. 重要参数说明

  • -s 100:缩放因子 (scale factor)

    • 核心参数,决定测试数据量大小
    • 值越大,数据量越大,测试越接近真实大规模场景
    • 常用值:10(小型), 50(中型), 100(中大型), 1000(大型)
  • -i:初始化模式 (initialize)

    • 只创建表结构和数据,不运行测试
  • -h localhost -U postgres:连接参数

    • 主机和用户名
  • test_db:目标数据库名

5. 初始化后的验证

初始化完成后,可以验证数据:

sql 复制代码
-- 连接到 test_db
psql -h localhost -U postgres -d test_db

-- 查看表大小和数据量
SELECT 
    schemaname,
    tablename,
    pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as total_size
FROM pg_tables 
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;

-- 查看行数统计
SELECT 
    'pgbench_accounts' as table_name,
    (SELECT count(*) FROM pgbench_accounts) as row_count
UNION ALL
SELECT 
    'pgbench_branches',
    (SELECT count(*) FROM pgbench_branches)
UNION ALL
SELECT 
    'pgbench_tellers',
    (SELECT count(*) FROM pgbench_tellers)
UNION ALL
SELECT 
    'pgbench_history',
    (SELECT count(*) FROM pgbench_history);

6. 后续操作建议

初始化完成后,就可以运行实际的性能测试了:

bash 复制代码
# 运行一个简单的基准测试
pgbench -h localhost -U postgres -c 10 -j 2 -T 60 test_db
# -c 10: 10个客户端并发
# -j 2: 2个工作线程
# -T 60: 运行60秒

7. 常见问题与注意事项

  1. 时间较长:当缩放因子较大时(如1000以上),初始化可能需要几分钟到几十分钟。

  2. 磁盘空间:确保有足够的磁盘空间,特别是对于大缩放因子。

  3. 内存使用:初始化过程会占用一定内存,但通常不会特别高。

  4. 取消初始化 :如果中途想取消,按 Ctrl+C,但已创建的数据不会被自动清理。

  5. 重新初始化 :如果想重新开始,需要先手动删除表或使用 -D 参数指定清理。

初始化完成后,pgbench创建了一个标准化的测试环境,适合进行数据库性能对比测试和压力测试。

我们收到一个pgbench测试的输出结果,需要解读这个结果。输出如下:

bash 复制代码
starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 100
query mode: simple
number of clients: 10
number of threads: 2
duration: 60 s
number of transactions actually processed: 77566
latency average = 7.736 ms
tps = 1292.666229 (including connections establishing)
tps = 1293.665486 (excluding connections establishing)

输出解读

  1. 测试配置参数
  • transaction type: <builtin: TPC-B (sort of)>
    使用内置的TPC-B类似事务,这是pgbench默认的事务脚本,模拟简单的银行交易。
  • scaling factor: 100
    缩放因子为100,与之前初始化时一致。这意味着测试数据量:branches表100行,tellers表1000行,accounts表1000万行。
  • query mode: simple
    使用简单查询模式(每个查询单独发送和接收)。另一种是扩展模式(extended,使用预处理语句)。
  • number of clients: 10
    模拟10个客户端并发执行事务。
  • number of threads: 2
    pgbench使用2个线程来管理这10个客户端。注意:线程数小于客户端数,所以每个线程要处理多个客户端。
  • duration: 60 s
    测试持续时间为60秒。
  1. 测试结果
  • number of transactions actually processed: 77566
    在60秒内,总共完成了77566个事务(即TPC-B类型的事务)。
  • latency average: 7.736 ms
    每个事务的平均延迟(响应时间)为7.736毫秒。注意:这是从客户端角度测量的往返时间。
  • tps = 1292.666229 (including connections establishing)
    包括建立连接时间在内的每秒事务数(TPS)为1292.67。因为pgbench在测试开始时建立连接,然后运行事务,所以这个TPS包括了连接建立的时间(但连接建立通常只在开始时发生,所以对长时间测试影响很小)。
  • tps = 1293.665486 (excluding connections establishing)
    不包括连接建立时间的TPS为1293.67。与上面的值非常接近,说明连接建立时间对整体TPS影响很小。
  1. 性能分析
  • TPS(每秒事务数):约1293。这是衡量数据库性能的关键指标,表示每秒能处理1293个类似TPC-B的事务。
    平均延迟:7.736毫秒。对于每个事务,平均需要7.736毫秒完成。
  1. 其他注意事项
  • 这个测试是在本地主机(localhost)上进行的,所以网络延迟几乎为零。如果在远程服务器上测试,网络延迟会影响结果。
  • 测试使用的是简单查询模式,如果使用扩展模式(预处理语句),性能可能会有所不同。
  • 测试结果受硬件(CPU、内存、磁盘)、PostgreSQL配置参数以及系统负载的影响。这个结果只能作为参考,实际生产环境需要更全面的测试。
  1. 如何改进测试
  • 可以调整客户端数(-c)和线程数(-j)来寻找最佳并发配置。
  • 可以尝试更复杂的自定义事务脚本,以模拟真实业务场景。
  • 可以延长测试时间(-T)以获得更稳定的平均值。
  • 可以结合数据库监控(如使用pg_stat_statements)分析查询性能。

典型的 pgbench 性能测试结果。以下是详细解读:

核心性能指标解读

1. 关键结果数据

指标 数值 含义与评价
总事务数 77,566 60秒内完成的事务总数
平均延迟 7.736 ms 每个事务的平均响应时间
TPS (含连接建立) 1,292.67 包含连接建立时间的每秒事务数
TPS (不含连接建立) 1,293.67 纯事务处理的每秒事务数

2. 测试配置参数

  • 事务类型 : TPC-B (类银行交易)
    • 包含:更新账户余额、更新分行余额、更新柜员余额、插入历史记录
  • 缩放因子 : 100
    • 对应:100个分行、1,000个柜员、1,000万个账户
  • 查询模式: simple (简单协议)
  • 客户端数: 10 (并发连接数)
  • 线程数: 2 (pgbench工作线程)
  • 持续时间: 60秒

性能分析

1. TPS 分析

  • 1,293 TPS 是一个中等偏上的性能表现
  • 影响因素
    • 硬件配置(CPU、内存、磁盘类型)
    • PostgreSQL 配置参数(shared_buffers、work_mem等)
    • 数据量大小(1,000万账户)
    • 本地测试(无网络延迟)

2. 延迟分析

  • 7.736ms 平均延迟 对于 TPC-B 事务是合理的
  • TPC-B 事务包含多个更新和插入操作
  • 在机械硬盘上通常为 10-30ms,SSD 上可降至 1-5ms

3. 连接开销分析

复制代码
TPS (含连接) = 1,292.67
TPS (不含连接) = 1,293.67
差值 = 1.0 TPS (仅 0.08% 差异)
  • 连接建立开销极小,说明连接池配置合理
  • 测试中连接是预先建立的,不是每个事务新建连接

与预期性能对比

1. 参考基准

硬件/配置 预期 TPS 范围 您的结果
普通机械硬盘 + 默认配置 500-1,500 1,293 (正常)
SSD + 优化配置 2,000-5,000+ -
高端 NVMe + 深度优化 10,000+ -

2. 性能瓶颈排查方向

如果 TPS 低于预期,可检查:

sql 复制代码
-- 1. 检查数据库配置
SHOW shared_buffers;      -- 推荐为内存的 25%
SHOW work_mem;            -- 推荐 4-32MB
SHOW max_connections;     -- 连接数限制
SHOW checkpoint_timeout;  -- 检查点间隔

-- 2. 监控系统资源
-- 使用 top/htop 查看 CPU 使用率
-- 使用 iostat 查看磁盘 I/O
-- 使用 vmstat 查看内存和交换分区

优化建议

1. 调整 pgbench 参数

bash 复制代码
# 增加客户端数(测试更高并发)
pgbench -h localhost -U postgres -c 20 -j 4 -T 60 my_test

# 使用 prepared 模式(减少解析开销)
pgbench -h localhost -U postgres -c 10 -j 2 -T 60 -M prepared my_test

# 只读测试(基准对比)
pgbench -h localhost -U postgres -c 10 -j 2 -T 60 -S my_test

2. PostgreSQL 配置优化

ini 复制代码
# postgresql.conf 关键参数
shared_buffers = 2GB           # 根据内存调整(25%)
effective_cache_size = 6GB     # 根据内存调整(75%)
work_mem = 16MB                # 每个操作的内存
max_connections = 100          # 最大连接数
checkpoint_timeout = 15min     # 检查点间隔

3. 进阶测试方案

bash 复制代码
# 1. 多阶段测试(模拟不同负载)
pgbench -h localhost -U postgres -c 10 -T 30 -M prepared my_test
pgbench -h localhost -U postgres -c 50 -T 30 -M prepared my_test
pgbench -h localhost -U postgres -c 100 -T 30 -M prepared my_test

# 2. 自定义脚本测试
cat custom_script.sql
\set aid random(1, 10000000)
SELECT abalance FROM pgbench_accounts WHERE aid = :aid;

pgbench -h localhost -U postgres -c 10 -T 60 -f custom_script.sql my_test

结果可视化建议

1. 创建性能趋势图

bash 复制代码
# 测试不同并发下的性能
for clients in 1 5 10 20 50 100
do
    pgbench -h localhost -U postgres -c $clients -j 2 -T 30 my_test | \
    grep "tps = " | tail -1 >> results.txt
done

2. 监控实时指标

bash 复制代码
# 在另一个终端监控
watch -n 1 "psql -h localhost -U postgres -d my_test -c \
\"SELECT count(*) FROM pgbench_accounts; \
SELECT count(*) FROM pgbench_history;\""

总结评价

您的测试结果 1,293 TPS 表明:

  1. 数据库运行正常:能稳定处理并发请求
  2. 配置基本合理:连接池、内存设置等没有明显问题
  3. 有优化空间:通过调整配置和硬件,TPS 可能提升 2-5 倍

下一步建议

  • 使用 -M prepared 模式重新测试
  • 逐步增加客户端数(-c 20, 50, 100)找到性能拐点
  • 调整 PostgreSQL 配置参数后对比测试
  • 如果使用机械硬盘,考虑升级到 SSD

判断 PostgreSQL 性能是否需要优化,主要看以下几个关键指标是否出现异常:

一、性能问题的明确信号

1. TPS 异常低(与硬件不匹配)

硬件配置 预期 TPS 范围 问题信号
NVMe SSD + 16GB+ 内存 < 5,000 TPS 明显偏低
SATA SSD + 8GB 内存 < 2,000 TPS 需要检查
机械硬盘 + 4GB 内存 < 500 TPS 可能有问题
云服务器基础型 低于同规格官方基准 50% 需要优化

2. 延迟异常高

延迟范围 评价 可能问题
< 10ms 优秀 -
10-50ms 正常 -
50-100ms 偏高 配置或硬件瓶颈
> 100ms 严重问题 必须优化

3. 资源使用异常

bash 复制代码
# 监控命令示例
top                    # CPU使用率 > 70% 持续
iostat -x 1            # await > 20ms, util > 80%
vmstat 1               # si/so > 0 (发生交换)

问题信号

  • CPU 持续 > 80%
  • 磁盘 I/O 等待时间 > 50ms
  • 内存交换频繁发生
  • 连接数接近 max_connections 限制

二、具体问题场景与解决方案

场景1:TPS 远低于预期

您的测试结果:1,293 TPS

  • 如果这是 NVMe SSD 的结果 → 需要优化
  • 如果这是 机械硬盘 的结果 → 基本正常

检查步骤

sql 复制代码
-- 1. 检查关键配置
SELECT name, setting, unit FROM pg_settings 
WHERE name IN ('shared_buffers', 'work_mem', 'max_connections', 'checkpoint_timeout');

-- 2. 检查当前活动连接
SELECT count(*) as total_connections,
       count(*) FILTER (WHERE state = 'active') as active_connections
FROM pg_stat_activity;

-- 3. 检查锁等待
SELECT blocked_locks.pid     AS blocked_pid,
       blocking_locks.pid    AS blocking_pid
FROM pg_catalog.pg_locks         blocked_locks
JOIN pg_catalog.pg_locks         blocking_locks 
    ON blocking_locks.locktype = blocked_locks.locktype
    AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
    AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
    AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
    AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
    AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
    AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
    AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
    AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
    AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
    AND blocking_locks.pid != blocked_locks.pid
WHERE NOT blocked_locks.granted;

场景2:延迟波动大或持续增长

问题表现

  • 测试开始时延迟 5ms,结束时延迟 50ms
  • P95/P99 延迟远高于平均延迟

解决方案

ini 复制代码
# postgresql.conf 调整
shared_buffers = 2GB              # 增加共享缓冲区
work_mem = 16MB                   # 增加排序内存
maintenance_work_mem = 256MB      # 增加维护操作内存
effective_cache_size = 6GB        # 优化器假设的缓存大小
random_page_cost = 1.1            # SSD设置为1.0-1.1

场景3:连接数问题

问题表现

复制代码
错误: sorry, too many clients already

解决方案

sql 复制代码
-- 1. 增加最大连接数(需重启)
ALTER SYSTEM SET max_connections = 200;

-- 2. 使用连接池(推荐)
-- 使用 pgbouncer 或 pgpool-II
-- 配置连接复用,减少实际数据库连接数

三、性能基准对比表

测试场景 正常范围 警告阈值 严重问题
TPC-B 测试
- NVMe SSD 5,000-15,000 TPS < 3,000 TPS < 1,000 TPS
- SATA SSD 2,000-5,000 TPS < 1,200 TPS < 500 TPS
- 机械硬盘 500-2,000 TPS < 300 TPS < 100 TPS
延迟 5-20ms 20-50ms > 50ms
CPU使用率 < 70% 70-90% > 90%
磁盘 I/O 等待 < 10ms 10-30ms > 30ms

四、系统化诊断流程

步骤1:快速健康检查

bash 复制代码
# 1. 检查数据库大小
psql -h localhost -U postgres -d my_test -c "
SELECT pg_size_pretty(pg_database_size('my_test')) as db_size;"

# 2. 检查表大小和膨胀
SELECT schemaname, tablename, 
       pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size,
       n_dead_tup as dead_tuples
FROM pg_stat_user_tables 
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC
LIMIT 10;

# 3. 检查索引使用情况
SELECT schemaname, tablename, indexname,
       idx_scan as index_scans
FROM pg_stat_user_indexes 
WHERE idx_scan = 0  -- 从未使用过的索引
ORDER BY schemaname, tablename;

步骤2:压力测试诊断

bash 复制代码
# 1. 逐步增加并发,观察性能变化
for clients in 1 5 10 20 50 100 200
do
    echo "=== 测试并发数: $clients ==="
    pgbench -h localhost -U postgres -c $clients -j 2 -T 30 my_test | \
    grep -E "tps = |latency average ="
done

# 2. 监控系统资源(另开终端)
watch -n 1 "top -b -n1 | head -20"

步骤3:分析性能瓶颈

sql 复制代码
-- 1. 查看等待事件
SELECT wait_event_type, wait_event, count(*)
FROM pg_stat_activity 
WHERE state = 'active'
GROUP BY 1, 2
ORDER BY 3 DESC;

-- 2. 查看慢查询(需要先开启)
-- 在 postgresql.conf 中设置:
-- shared_preload_libraries = 'pg_stat_statements'
-- pg_stat_statements.track = all

SELECT query, calls, total_time, mean_time,
       rows, 100.0 * shared_blks_hit / nullif(shared_blks_hit + shared_blks_read, 0) AS hit_percent
FROM pg_stat_statements 
ORDER BY mean_time DESC 
LIMIT 10;

五、必须立即优化的场景

  1. TPS 持续下降:测试期间 TPS 越来越低
  2. 延迟指数增长:从 10ms 增长到 100ms+
  3. 错误率 > 1%:大量连接超时或失败
  4. CPU 持续 100%:且 TPS 很低
  5. 磁盘 I/O 等待 > 100ms:明显磁盘瓶颈
  6. 内存交换频繁:si/so 持续 > 0

六、优化优先级

高优先级(立即处理):

  1. 内存配置错误shared_buffers 太小
  2. 检查点过频checkpoint_timeout 太短
  3. 连接数不足:频繁连接拒绝
  4. 缺少索引:全表扫描频繁

中优先级(近期优化):

  1. work_mem 不足:大量磁盘排序
  2. autovacuum 配置:表膨胀严重
  3. WAL 配置:写入性能瓶颈

低优先级(长期优化):

  1. 查询重写:复杂查询优化
  2. 分区表:大数据量表
  3. 复制与读写分离:高并发场景

总结判断标准

您的 1,293 TPS 是否需要优化?

  1. 先看硬件

    • 如果是 机械硬盘:正常,可小优化
    • 如果是 SSD:偏低,需要优化
    • 如果是 NVMe:明显偏低,必须优化
  2. 再看趋势

    • 运行 60 秒 TPS 稳定 → 正常
    • TPS 持续下降 → 有问题
  3. 最后看资源

    • CPU < 50%,磁盘 I/O < 20ms → 配置可优化
    • CPU > 80%,磁盘 I/O > 50ms → 硬件瓶颈

建议行动

  1. 先确认硬件类型
  2. 运行 topiostat 查看资源使用
  3. 根据上述诊断流程找出瓶颈
  4. 针对性调整配置后重新测试

记住:优化前一定要有基准测试数据,优化后对比验证效果。

相关推荐
埋头编程~1 天前
【测试报告】网页端博客系统
功能测试·压力测试·性能测试·测试
汽车仪器仪表相关领域1 天前
便携即战力,全域无短板:PL-1 袖珍记录仪核心重构与场景落地全解
功能测试·重构·汽车·压力测试·可用性测试·ab测试
张永清-老清1 天前
每周读书与学习->Jmeter中如何使用Bean Shell脚本(二)Bean Shell的基础语法之变量与数据类型
学习·测试工具·jmeter·压力测试·性能调优·jmeter性能测试·性能分析
汽车仪器仪表相关领域2 天前
SSI-4 PLUS 简易传感器接口:多场景采集 “即插即用” 的终极解决方案
功能测试·测试工具·单元测试·压力测试·可用性测试·模块测试·安全性测试
Saniffer_SH2 天前
【高清视频】4小时带你了解Saniffer公司针对PCIe Gen6测试的最新白皮书15.X
网络·人工智能·驱动开发·嵌入式硬件·测试工具·计算机外设·压力测试
汽车仪器仪表相关领域3 天前
ZRT-V 机器人减速器寿命测试系统:以长效智能,破局可靠性验证困局
功能测试·安全·机器人·汽车·压力测试·可用性测试
Saniffer_SH3 天前
【高清视频】SerialTek PCIe 5.0/6.0 协议分析仪API自动化编程演示
网络·人工智能·驱动开发·嵌入式硬件·测试工具·自动化·压力测试
Saniffer_SH3 天前
【高清视频】如何针对电动汽车进行通信可靠性测试、故障注入与功率分析?
服务器·驱动开发·测试工具·fpga开发·计算机外设·硬件架构·压力测试