PosgreSQL快速参数调优和sysbench压测
关于PostgreSQL的性能调优可以参考《PostgreSQL 9.0 High Performance》,以及朱贤文在2014 PostgreSQL中国用户大会上分享的《高性能Postgres 最佳实践》。当然,首先还是应该看看PostgreSQL手册的相关章节。我们在调优时不必每个细节都做到最优,抓住主要矛盾即可。因为有些东西不在你的控制之下,或者那样优化之后维护起来麻烦。下面尝试在虚机下进行快速的PostgreSQL参数调优。
1. 虚机环境
CPU: 4 core
Mem: 8G
OS: CentOS 6.3(64 Bit)
PostgreSQL:9.4.5
sysbench:0.4.12
文件系统:ext4
2.参数设置
基本的性能参数设置可以利用下面这个在线小工具评估。
http://pgtune.leopard.in.ua/
填入系统信息,并固定最大连接数为300后,选择不同DB Type,这个工具会给出不同的参数。
Web applications
max_connections = 300 shared_buffers = 2GB effective_cache_size = 6GB work_mem = 6990kB maintenance_work_mem = 512MB checkpoint_segments = 32 checkpoint_completion_target = 0.7 wal_buffers = 16MB default_statistics_target = 100
Online transaction processing systems
max_connections = 300 shared_buffers = 2GB effective_cache_size = 6GB work_mem = 6990kB maintenance_work_mem = 512MB checkpoint_segments = 64 checkpoint_completion_target = 0.9 wal_buffers = 16MB default_statistics_target = 100
Data warehouses
max_connections = 300 shared_buffers = 2GB effective_cache_size = 6GB work_mem = 3495kB maintenance_work_mem = 1GB checkpoint_segments = 128 checkpoint_completion_target = 0.9 wal_buffers = 16MB default_statistics_target = 500
上面3种DB Type,越往后写越重,checkpoint的频率也调得越低。由于后面要做OLTP的性能评估,所以选用Online transaction processing systems的设置。
综合考虑log等需求,初步在postgresql.conf中设置参数如下
listen_addresses = '*' port = 5432 max_connections = 300 shared_buffers = 2GB effective_cache_size = 6GB work_mem = 6990kB maintenance_work_mem = 512MB checkpoint_segments = 64 checkpoint_completion_target = 0.9 wal_buffers = 16MB default_statistics_target = 100 logging_collector = on log_directory = 'pg_log' log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' log_truncate_on_rotation = on log_rotation_age = 1440 log_rotation_size = 100000 log_line_prefix='%m %p %x' wal_level = hot_standby
流复制时需要设置wal_level = hot_standby,单机场景下可以设置其它值以输出更少的WAL日志。
下面这几个参数有些需要在性能和持久性之间平衡,先全部采用默认值。
wal_sync_method = fsync commit_delay = 0 synchronous_commit = on full_page_writes = on fsync = on
3.测试方法
用sysbench 做oltp的性能测试,不管使用simple还是complex测试模式,sysbench prepare时创建单个相同的测试表(那就不可能测到join了)。
建表语句如下
CREATE TABLE sbtest (id SERIAL NOT NULL , k integer DEFAULT '0' NOT NULL, c char(120) DEFAULT '' NOT NULL, pad char(60) DEFAULT '' NOT NULL, PRIMARY KEY (id) )
CREATE INDEX k on sbtest(k)
|
然后插入数据,插入数据量由oltp-table-size决定。
INSERT INTO sbtest(k, c, pad) VALUES (0,' ','qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt')
|
当插入数据量很大时,由于每个插入语句都是一次提交,因此速度很慢。我们可以用下面的方法手动准备数据,而不是使用sysbench的prepare。
DROP TABLE sbtest;
CREATE TABLE sbtest (id SERIAL NOT NULL , k integer DEFAULT '0' NOT NULL, c char(120) DEFAULT '' NOT NULL, pad char(60) DEFAULT '' NOT NULL, PRIMARY KEY (id) );
CREATE INDEX k on sbtest(k);
INSERT INTO sbtest(k, c, pad) select 0,' ','qqqqqqqqqqwwwwwwwwwweeeeeeeeeerrrrrrrrrrtttttttttt' from generate_series(1,5000000);
|
插入500万记录后,数据表大小大约为1GB。
postgres=# \d+
List of relations
Schema | Name | Type | Owner | Size | Description
--------+------------------+----------+----------+------------+-------------
public | sbtest | table | postgres | 1056 MB |
public | sbtest_id_seq | sequence | postgres | 8192 bytes |
(2 rows)
|
simple模式的测试语句如下
SELECT c from sbtest where id=$1
|
$1是个取值在oltp-table-size范围内的随机数,随机数的生成算法由oltp-dist-type决定,包括uniform,gaussian,special三种,默认是special,生成的随机数有75%(由oltp-dist-pct控制)集中在一个1%(由oltp-dist-pct控制)的热点区域。
complex模式且oltp-read-only=on时的测试语句如下
BEGIN
SELECT c from sbtest where id=$1
SELECT c from sbtest where id=$1
SELECT c from sbtest where id=$1
SELECT c from sbtest where id=$1
SELECT c from sbtest where id=$1
SELECT c from sbtest where id=$1
SELECT c from sbtest where id=$1
SELECT c from sbtest where id=$1
SELECT c from sbtest where id=$1
SELECT c from sbtest where id=$1
SELECT c from sbtest where id between $1 and $2
SELECT SUM(K) from sbtest where id between $1 and $2
SELECT c from sbtest where id between $1 and $2 order by c
SELECT DISTINCT c from sbtest where id between $1 and $2 order by c
COMMIT
|
上面的between范围查询,范围大小为100(由oltp-range-size控制)。
complex模式且oltp-read-only=off时的测试语句如下
BEGIN
SELECT c from sbtest where id=$1
SELECT c from sbtest where id=$1
SELECT c from sbtest where id=$1
SELECT c from sbtest where id=$1
SELECT c from sbtest where id=$1
SELECT c from sbtest where id=$1
SELECT c from sbtest where id=$1
SELECT c from sbtest where id=$1
SELECT c from sbtest where id=$1
SELECT c from sbtest where id=$1
SELECT c from sbtest where id between $1 and $2
SELECT SUM(K) from sbtest where id between $1 and $2
SELECT c from sbtest where id between $1 and $2 order by c
SELECT DISTINCT c from sbtest where id between $1 and $2 order by c
UPDATE sbtest set k=k+1 where id=$1
UPDATE sbtest set c=$1 where id=$2
UPDATE sbtest set k=k+1 where id=$1
DELETE from sbtest where id=$1
INSERT INTO sbtest values($1,0,' ','aaaaaaaaaaffffffffffrrrrrrrrrreeeeeeeeeeyyyyyyyyyy')
COMMIT
|
但是在并发数很高的情况下,会报下面的错误
ERROR: duplicate key value violates unique constraint "sbtest_pkey"
为了回避这个问题,参考德哥的方法临时修改sysbench的代码(这个问题和PostgreSQL的MVCC实现机制有关,详见http://blog.chinaunix.net/uid-20726500-id-5289907.html)。
修改方法如下:
修改sysbench-0.4.12/sysbench/tests/oltp/sb_oltp.c
找到
/* Prepare the insert statement */
snprintf(query, MAX_QUERY_LEN, "INSERT INTO %s values(?,0,' ',"
"'aaaaaaaaaaffffffffffrrrrrrrrrreeeeeeeeeeyyyyyyyyyy')",
args.table_name);
|
改成
/* Prepare the insert statement */
if (args.auto_inc)
snprintf(query, MAX_QUERY_LEN, "INSERT INTO %s(k,c,pad) values(0,' ',"
"'aaaaaaaaaaffffffffffrrrrrrrrrreeeeeeeeeeyyyyyyyyyy')",
args.table_name);
else
snprintf(query, MAX_QUERY_LEN, "INSERT INTO %s values(?,0,' ',"
"'aaaaaaaaaaffffffffffrrrrrrrrrreeeeeeeeeeyyyyyyyyyy')",
args.table_name);
|
参考:http://blog.163.com/digoal@126/blog/static/1638770402013414549515/
修改后,最后一条INSERT句就变成了下面这样了
INSERT INTO sbtest(k,c,pad) values(0,' ','aaaaaaaaaaffffffffffrrrrrrrrrreeeeeeeeeeyyyyyyyyyy')
|
注:其实更加正确的做法应该是使用sysbench 0.5而不是0.4,sysbench 0.5没有这个问题,而且0.5支持lua脚本,支持的测试方式更灵活。
4. 测试
simple模式
执行下面的命令,100并发,TPS为29200.43,测试时CPU被占满,达到CPU极限。
[postgres@node1 ~]$ sysbench --test=oltp --db-driver=pgsql --pgsql-host=127.0.0.1 --pgsql-port=5432 --pgsql-user=postgres --pgsql-password=postgres --pgsql-db=postgres --oltp-table-size=5000000 --num-threads=100 --max-requests=0 --max-time=60 --oltp-test-mode=simple --oltp-read-only=on run sysbench 0.4.12: multi-threaded system evaluation benchmark Running the test with following options: Number of threads: 100 Doing OLTP test. Running simple OLTP test Doing read-only test Using Special distribution (12 iterations, 1 pct of values are returned in 75 pct cases) Using "BEGIN" for starting transactions Using auto_inc on the id column Threads started! Time limit exceeded, exiting... (last message repeated 99 times) Done. OLTP test statistics:queries performed:read: 1752165write: 0other: 0total: 1752165transactions: 1752165 (29200.43 per sec.)deadlocks: 0 (0.00 per sec.)read/write requests: 1752165 (29200.43 per sec.)other operations: 0 (0.00 per sec.) Test execution summary:total time: 60.0048stotal number of events: 1752165total time taken by event execution: 5993.5646per-request statistics:min: 0.04msavg: 3.42msmax: 968.42msapprox. 95 percentile: 0.34ms Threads fairness:events (avg/stddev): 17521.6500/2549.74execution time (avg/stddev): 59.9356/0.01
complex模式且oltp-read-only=on
执行下面的命令,100并发,TPS为1505.38,测试时CPU被占满,达到CPU极限,其中sysbench进程的CPU率大约80%。
[postgres@node1 ~]$ sysbench --test=oltp --db-driver=pgsql --pgsql-host=127.0.0.1 --pgsql-port=5432 --pgsql-user=postgres --pgsql-password=postgres --pgsql-db=postgres --oltp-table-size=5000000 --num-threads=100 --max-requests=0 --max-time=60 --oltp-test-mode=complex --oltp-read-only=on run sysbench 0.4.12: multi-threaded system evaluation benchmark Running the test with following options: Number of threads: 100 Doing OLTP test. Running mixed OLTP test Doing read-only test Using Special distribution (12 iterations, 1 pct of values are returned in 75 pct cases) Using "BEGIN" for starting transactions Using auto_inc on the id column Threads started! Time limit exceeded, exiting... (last message repeated 99 times) Done. OLTP test statistics:queries performed:read: 1265264write: 0other: 180752total: 1446016transactions: 90376 (1505.38 per sec.)deadlocks: 0 (0.00 per sec.)read/write requests: 1265264 (21075.27 per sec.)other operations: 180752 (3010.75 per sec.) Test execution summary:total time: 60.0355stotal number of events: 90376total time taken by event execution: 5998.5193per-request statistics:min: 1.98msavg: 66.37msmax: 4032.00msapprox. 95 percentile: 161.49ms Threads fairness:events (avg/stddev): 903.7600/74.26execution time (avg/stddev): 59.9852/0.04
complex模式且oltp-read-only=off
执行下面的命令,100并发,TPS为1232.77,测试时CPU被占满,其中sysbench进程的CPU率大约80%,磁盘Busy大约10+%,磁盘写入也是10+MB/s。
[postgres@node1 ~]$ sysbench --test=oltp --db-driver=pgsql --pgsql-host=127.0.0.1 --pgsql-port=5432 --pgsql-user=postgres --pgsql-password=postgres --pgsql-db=postgres --oltp-table-size=5000000 --num-threads=100 --max-requests=0 --max-time=60 --oltp-test-mode=complex --oltp-read-only=off run sysbench 0.4.12: multi-threaded system evaluation benchmark Running the test with following options: Number of threads: 100 Doing OLTP test. Running mixed OLTP test Using Special distribution (12 iterations, 1 pct of values are returned in 75 pct cases) Using "BEGIN" for starting transactions Using auto_inc on the id column Threads started! Time limit exceeded, exiting... (last message repeated 99 times) Done. OLTP test statistics:queries performed:read: 1035986write: 369995other: 147998total: 1553979transactions: 73999 (1232.77 per sec.)deadlocks: 0 (0.00 per sec.)read/write requests: 1405981 (23422.71 per sec.)other operations: 147998 (2465.55 per sec.) Test execution summary:total time: 60.0264stotal number of events: 73999total time taken by event execution: 5998.7493per-request statistics:min: 2.69msavg: 81.07msmax: 547.21msapprox. 95 percentile: 199.32ms Threads fairness:events (avg/stddev): 739.9900/23.37execution time (avg/stddev): 59.9875/0.04
5. 参数的优化
由于上面测试场景的性能瓶颈都在CPU,基本没什么可优化的,(实际试了下,确实也没有优化效果)。如果瓶颈在刷盘可以通过调节下面几个参数优化。
No
|
参数
|
说明
|
风险
|
---|---|---|---|
1 | wal_sync_method = fdatasync | WAL刷盘的系统调用,根据之前的测试fdatasync比fsync性能好。但是Linux下的默认值就是fdatasync所以也不同修改。 | 无风险 |
2 | commit_delay = 100 | 提交延迟,单位是微妙(不是毫秒),以进行组提交。 |
设得太大会影响事务的响应时间。 注)实际压测发现效果不稳定。因并发连接数,热数据分布,commit_delay等的不同,有时性能提高有时降低,所以优化这个值要根据实际的应用环境。 |
3 |
synchronous_commit = off |
异步提交,WAL刷盘交给OS | OS crash时,可能丢失最近的提交。 |
4 | full_page_writes = off | 在WAL中checkpoint后的第一次修改page时不写全page数据 | 对不支持原子写的文件系统或存储设备上,OS crash时,数据文件会损坏。 |
5 | fsync = off | 不刷盘,完全交给OS刷 | OS crash时,数据文件可能会损坏。 |
上面的full_page_writes和fsync非常危险,修改时务必慎重!
6. 补充:page大小的调整
还有一种经常被提到的优化方法是修改page大小,PostgreSQL默认的page大小是8K,编译时可以指定。
./configure --with-blocksize=16
下面是16K和8K的性能对比,从下面可以看出16K反而性能变差,所以16K的优化方法一定要看机器环境和场景的(可能更适合OLAP吧)。而且改page大小要重新编译源码,8K的数据目录和16K的又不兼容,不能互相复制。所以修改page大小要慎重。
100线程,500W数据的sysbench测试出的tps值:
test mode
|
8K
|
16K
|
---|---|---|
simple | 29200.43 | 28795.46 |
complex模式且oltp-read-only=on | 1505.38 | 1462.40 |
complex模式且oltp-read-only=off | 1232.77 | 1058.48 |
PosgreSQL快速参数调优和sysbench压测相关推荐
- 笔记 | 百度飞浆AI达人创造营:深度学习模型训练和关键参数调优详解
笔记 | 百度飞浆AI达人创造营:深度学习模型训练和关键参数调优详解 针对特定场景任务从模型选择.模型训练.超参优化.效果展示这四个方面进行模型开发. 一.模型选择 从任务类型出发,选择最合适的模型. ...
- 深度学习模型训练和关键参数调优详解
深度学习模型训练和关键参数调优详解 一.模型选择 1.回归任务 人脸关键点检测 2.分类任务 图像分类 3.场景任务 目标检测 人像分割 文字识别 二.模型训练 1.基于高层API训练模型 加载数据集 ...
- AI4DB:openGauss人工智能参数调优之X-Tuner
X-Tuner:参数调优与诊断 一.概述 二.使用准备 三.使用示例 四.获取帮助 五.命令参考 六.常见问题处理 一.概述 增量物化视图可以对物化视图增量刷新,需要用户手动执行语句完成对物化视图 ...
- 05:Sysbench压测-innodb_deadlock_detect参数对性能的影响
目录 sysbench压测-innodb_deadlock_detect参数对性能的影响 一.OLTP测试前准备 二.进行OLTP测试 三.测试结果解读: 四.关于测试后的结论: 五.关于测试后的性能 ...
- CPU-IO-网络-内核参数调优
一. 有关使用CPU资源的调优 1. nice概述 在LINUX系统中,Nice值的范围从-20到+19(不同系统的值范围是不一样的),正值表示低优先级,负值表示高优先级,值为零则表示不会调整该进程的 ...
- Redis数据结构与参数调优
一.Redis基础入门 1.Redis 简介 Redis是一种高级key-value数据库.它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富.有字符串,链表.哈希.集合和有序集 ...
- spark 资源参数调优
资源参数调优 了解完了Spark作业运行的基本原理之后,对资源相关的参数就容易理解了.所谓的Spark资源参数调优,其实主要就是对Spark运行过程中各个使用资源的地方,通过调节各种参数,来优化资源使 ...
- 机器学习之超参数调优——超参数调优的方法
超参数调优的方法 概述 网格搜索 随机搜索 贝叶斯优化算法 概述 对于很多算法工程师来说, 超参数调优是件非常头疼的事.除了根据经验设定所谓的"合 理值"之外, 一般很难找到合理的 ...
- 【Flink】Flink on RocksDB 参数调优指南
1. 背景 对于需要保存超大状态(远超于内存容量)的流计算场景来说,目前 RocksDB [1] 是 Flink 平台上官方实现的唯一选择.业界也有使用 Redis 等其他服务作为状态后端的方案,但终 ...
最新文章
- springbooot mysql_Spring Boot入门(2)使用MySQL数据库
- oracle表空间压缩
- SSRS 使用(1)建立简单的Report
- SparseArray代替HashMap
- gym103117L. Spicy Restaurant
- Jakarta EE 8状态
- Linux学习笔记:Linux常用命令操作
- 浅谈jQuery宽高及其应用
- 2021-2025年中国电子液体处理系统行业市场供需与战略研究报告
- 【poj1995】Raising Modulo Numbers
- 【排序】内部排序算法实现
- 这份Java面试题,阿里P7的正确率都不到50%!!
- 设计一个服务器资源管理系统,基于虚拟化技术的服务器资源管理系统的设计与实现.pdf...
- Mybatis foreach逗号分隔字符串遍历方式
- Windows 各版本默认自带IE版本
- GPLv2许可证正经人话翻译
- word文档另存为pdf格式,如何设置导航栏
- 哥德尔定理的背景知识1:戴德金的数观念——哥德尔逻辑与哲学之3
- C++基础到实战开发(附带课程源码)
- EGE基础入门篇(九):双缓冲与手动渲染
热门文章
- python 切片_知乎问答之 Python 切片整理
- keras faster物体检测_全网 | 深度学习目标检测算法(精选12篇)
- [码海拾贝 之Perl]在字符串数组中查找特定的字符串是否存在
- html 文字中不换行怎么写,HTML让字体在一行内显示不换行
- java用cmd编译access数据库_java直接存取MS Access的mdb数据库文件
- Springboot启动完毕后提供了立刻执行自定义程序的两个接口类
- 5绘制收银台程序_进来学知识了:实操之C/C++的绘制
- 【老军医方】在脱发过程中遇到的各种疑难杂症
- 华为100万部鸿蒙,2019年Q4发布 华为100万部鸿蒙OS手机已开测
- python实现并发判重_寻找python大神!!!python如何多线程并发?