前不久,一个朋友所在的公司,业务人员整天都喊慢。

朋友是搞开发的,不是很懂DB,他说他们应用的其实没什么问题,但是就是每天一到高峰期就办理特别的慢啊,各种堵塞,一堆请求无法完成。他们没有专门的DBA,想找我帮忙看看。

我下班后打开他们的数据库看了几眼,让我大跌眼睛,数据库全部都是默认配置的参数。然后就给他们随便修改了一通,告诉他们重启了一下数据库。到了第二天他反映,大哥,你也太神了,昨天做了什么操作,我们的数据库就突然就变快了。

我说:啥也没做啊,就是根据经验值把默认参数调了一下,草率的很!你们参数都是开箱即用的默认值。当做生产使用肯定不行。

PostgreSQL应该调整的参数

max_connections

允许的最大客户端连接数。这个参数设置大小和work_mem有一些关系。配置的越高,可能会占用系统更多的内存。通常可以设置数百个连接,如果要使用上千个连接,建议配置连接池来减少开销。

shared_buffers

PostgreSQL使用自己的缓冲区,也使用Linux操作系统内核缓冲OS Cache。这就说明数据两次存储在内存中,首先是PostgreSQL缓冲区,然后是操作系统内核缓冲区。与其他数据库不同,PostgreSQL不提供直接IO,所以这又被称为双缓冲。PostgreSQL缓冲区称为shared_buffer,建议设置为物理内存的1/4。而实际配置取决于硬件配置和工作负载,如果你的内存很大,而你又想多缓冲一些数据到内存中,可以继续调大shared_buffer

Effective_cache_size

这个参数主要用于Postgre查询优化器。是单个查询可用的磁盘高速缓存的有效大小的一个假设,是一个估算值,它并不占据系统内存。由于优化器需要进行估算成本,较高的值更有可能使用索引扫描,较低的值则有可能使用顺序扫描。一般这个值设置为内存的1/2是正常保守的设置,设置为内存的3/4是比较推荐的值。通过free命令查看操作系统的统计信息,您可能会更好的估算该值。

[pg@e22 ~]$ free -g              total        used        free      shared  buff/cache   availableMem:             62           2           5          16          55          40Swap:             7           0           7

work_mem

这个参数主要用于写入临时文件之前内部排序操作和散列表使用的内存量,增加work_mem参数将使PostgreSQL可以进行更大的内存排序。这个参数和max_connections有一些关系,假设你设置为30MB,则40个用户同时执行查询排序,很快就会使用1.2GB的实际内存。同时对于复杂查询,可能会运行多个排序和散列操作,例如涉及到8张表进行合并排序,此时就需要8倍的work_mem

如下面案例所示,该环境使用4MB的work_mem,在执行排序操作的时候,使用的Sort Methodexternal merge Disk

kms=> explain (analyze,buffers) select * from KMS_BUSINESS_HALL_TOTAL  order by buss_query_info;                                                                       QUERY PLAN                                                                        --------------------------------------------------------------------------------------------------------------------------------------------------------- Gather Merge  (cost=262167.99..567195.15 rows=2614336 width=52) (actual time=2782.203..5184.442 rows=3137204 loops=1)   Workers Planned: 2   Workers Launched: 2   Buffers: shared hit=68 read=25939, temp read=28863 written=28947   ->  Sort  (cost=261167.97..264435.89 rows=1307168 width=52) (actual time=2760.566..3453.783 rows=1045735 loops=3)         Sort Key: buss_query_info         Sort Method: external merge  Disk: 50568kB         Worker 0:  Sort Method: external merge  Disk: 50840kB         Worker 1:  Sort Method: external merge  Disk: 49944kB         Buffers: shared hit=68 read=25939, temp read=28863 written=28947         ->  Parallel Seq Scan on kms_business_hall_total  (cost=0.00..39010.68 rows=1307168 width=52) (actual time=0.547..259.524 rows=1045735 loops=3)               Buffers: shared read=25939 Planning Time: 0.540 ms Execution Time: 5461.516 ms(14 rows)

当我们把参数修改成512MB的时候,可以看到Sort Method变成了quicksort Memory,变成了内存排序。

kms=> set work_mem to "512MB";SETkms=> explain (analyze,buffers) select * from KMS_BUSINESS_HALL_TOTAL  order by buss_query_info;                                                                QUERY PLAN                                                                ------------------------------------------------------------------------------------------------------------------------------------------ Sort  (cost=395831.79..403674.80 rows=3137204 width=52) (actual time=7870.826..8204.794 rows=3137204 loops=1)   Sort Key: buss_query_info   Sort Method: quicksort  Memory: 359833kB   Buffers: shared hit=25939   ->  Seq Scan on kms_business_hall_total  (cost=0.00..57311.04 rows=3137204 width=52) (actual time=0.019..373.067 rows=3137204 loops=1)         Buffers: shared hit=25939 Planning Time: 0.081 ms Execution Time: 8419.994 ms(8 rows)

maintenance_work_mem

指定维护操作使用的最大内存量,例如(Vacuum、Create Index和Alter Table Add Foreign Key),默认值是64MB。由于通常正常运行的数据库中不会有大量并发的此类操作,可以设置的较大一些,提高清理和创建索引外键的速度。

postgres=# set maintenance_work_mem to "64MB";SETTime: 1.971 mspostgres=# create index idx1_test on test(id);CREATE INDEXTime: 7483.621 ms (00:07.484)postgres=# set maintenance_work_mem to "2GB";SETTime: 0.543 mspostgres=# drop index idx1_test;DROP INDEXTime: 133.984 mspostgres=# create index idx1_test on test(id);CREATE INDEXTime: 5661.018 ms (00:05.661)

可以看到在使用默认的64MB创建索引,速度为7.4秒,而设置为2GB后,创建速度是5.6秒

wal_sync_method

每次发生事务后,PostgreSQL会强制将提交写到WAL日志的方式。可以使用pg_test_fsync命令在你的操作系统上进行测试,fdatasync是Linux上的默认方法。如下所示,我的环境测试下来fdatasync还是速度可以的。不支持的方法像fsync_writethrough直接显示n/a。

postgres=# show wal_sync_method ; wal_sync_method ----------------- fdatasync(1 row)

[pg@e22 ~]$ pg_test_fsync -s 33 seconds per testO_DIRECT supported on this platform for open_datasync and open_sync.

Compare file sync methods using one 8kB write:(in wal_sync_method preference order, except fdatasync is Linux's default)        open_datasync                      4782.871 ops/sec     209 usecs/op        fdatasync                          4935.556 ops/sec     203 usecs/op        fsync                              3781.254 ops/sec     264 usecs/op        fsync_writethrough                              n/a        open_sync                          3850.219 ops/sec     260 usecs/op

Compare file sync methods using two 8kB writes:(in wal_sync_method preference order, except fdatasync is Linux's default)        open_datasync                      2469.646 ops/sec     405 usecs/op        fdatasync                          4412.266 ops/sec     227 usecs/op        fsync                              3432.794 ops/sec     291 usecs/op        fsync_writethrough                              n/a        open_sync                          1929.221 ops/sec     518 usecs/op

Compare open_sync with different write sizes:(This is designed to compare the cost of writing 16kB in different writeopen_sync sizes.)         1 * 16kB open_sync write          3159.780 ops/sec     316 usecs/op         2 *  8kB open_sync writes         1944.723 ops/sec     514 usecs/op         4 *  4kB open_sync writes          993.173 ops/sec    1007 usecs/op         8 *  2kB open_sync writes          493.396 ops/sec    2027 usecs/op        16 *  1kB open_sync writes          249.762 ops/sec    4004 usecs/op

Test if fsync on non-write file descriptor is honored:(If the times are similar, fsync() can sync data written on a differentdescriptor.)        write, fsync, close                3719.973 ops/sec     269 usecs/op        write, close, fsync                3651.820 ops/sec     274 usecs/op

Non-sync'ed 8kB writes:        write                            400577.329 ops/sec       2 usecs/op

wal_buffers

事务日志缓冲区的大小,PostgreSQL将WAL记录写入缓冲区,然后再将缓冲区刷新到磁盘。在PostgreSQL 12版中,默认值为-1,也就是选择等于shared_buffers的1/32 。如果自动的选择太大或太小可以手工设置该值。一般考虑设置为16MB。

synchronous_commit

客户端执行提交,并且等待WAL写入磁盘之后,然后再将成功状态返回给客户端。可以设置为on,remote_apply,remote_write,local,off等值。默认设置为on。如果设置为off,会关闭sync_commit,客户端提交之后就立马返回,不用等记录刷新到磁盘。此时如果PostgreSQL实例崩溃,则最后几个异步提交将会丢失。

default_statistics_target

PostgreSQL使用统计信息来生成执行计划。统计信息可以通过手动Analyze命令或者是autovacuum进程启动的自动分析来收集,default_statistics_target参数指定在收集和记录这些统计信息时的详细程度。默认值为100对于大多数工作负载是比较合理的,对于非常简单的查询,较小的值可能会有用,而对于复杂的查询(尤其是针对大型表的查询),较大的值可能会更好。为了不要一刀切,可以使用ALTER TABLE .. ALTER COLUMN .. SET STATISTICS覆盖特定表列的默认收集统计信息的详细程度。

checkpoint_timeout、max_wal_size,min_wal_size、checkpoint_completion_target

了解这两个参数以前,首先我们来看一下,触发检查点的几个操作。

  • 直接执行checkpoint命令
  • 执行需要检查点的命令(例如pg_start_backup,Create database,pg_ctl stop/start等等)
  • 自上一个检查点以来,达到了已经配置的时间量(checkpoint_timeout )
  • 自上一个检查点以来生成的WAL数量(max_wal_size)

使用默认值,检查点将在checkpoint_timeout=5min。也就是每5分钟触发一次。而max_wal_size设置是自动检查点之间增长的最大预写日志记录(WAL)量。默认是1GB,如果超过了1GB,则会发生检查点。这是一个软限制。在一个特殊的情况下,比如系统遭遇到短时间的高负载,日志产生几秒种就可以达到1GB,这个速度已经明显超过了checkpoint_timeout ,pg_wal目录的大小会急剧增加。此时我们可以从日志中看到相关类似的警告。

LOG:  checkpoints are occurring too frequently (9 seconds apart)HINT:  Consider increasing the configuration parameter "max_wal_size".LOG:  checkpoints are occurring too frequently (2 seconds apart)HINT:  Consider increasing the configuration parameter "max_wal_size".

所以要合理配置max_wal_size,以避免频繁的进行检查点。一般推荐设置为16GB以上,不过具体设置多大还需要和工作负荷相匹配。

min_wal_size参数是只要 WAL 磁盘使用量保持在这个设置之下,在做检查点时,旧的 WAL 文件总是被回收以便未来使用,而不是直接被删除。

而检查点的写入不是全部立马完成的,PostgreSQL会将一次检查点的所有操作分散到一段时间内。这段时间由参数checkpoint_completion_target控制,它是一个分数,默认为0.5。也就是在两次检查点之间的0.5比例完成写盘操作。如果设置的很小,则检查点进程就会更加迅速的写盘,设置的很大,则就会比较慢。一般推荐设置为0.9,让检查点的写入分散一点。但是缺点就是出现故障的时候,影响恢复的时间。

使用PGTune工具来配置参数

对于朋友这样的公司,没有DBA专业人士,我一般会建议他们使用PGTune来配置参数,这款工具是在线软件,链接地址。设置很简单,你只需要知道你的数据库版本,操作系统类型,内存数量,CPU数量,磁盘类型,连接数,还有应用的类型。就可以轻轻松松得到一些建议的参数值。


使用postgresqltuner来优化参数

当然我们还可以使用postgresqltuner工具来优化参数,作者说受到了mysqltuner的启发,它是perl脚本写的。链接地址

这个软件使用起来也很简单,直接下载解压,执行脚本就行了。

postgresqltuner.pl --host=dbhost --database=testdb --user=username --password=qwerty

执行输出结果如下:


这个软件要比PGTune要专业一些,它还输出了一些操作系统的配置,同时它根据数据库当前的负载来判断内存参数是否合理,类似于Advisor。

总结

最后来做个ending吧,系统默认的配置只适合自己玩玩,并不适合开箱即用。还是需要根据DBA的专业经验来进行相关参数的配置,如果没有专业的DBA童鞋,也可以使用PGTune或者是postgresqltuner脚本来进行一些优化,做完这些优化,系统性能将会大幅提升。

参考文档

https://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Serverhttps://www.percona.com/blog/2018/08/31/tuning-postgresql-database-parameters-to-optimize-performance/

mvd没什么每次参数双都多一个逗号_必看!PostgreSQL参数优化相关推荐

  1. mvd没什么每次参数双都多一个逗号_学服装设计后,家里多了哪些奇怪又可爱的宝藏物品?...

    如果你身边有一个学习服装设计的小伙伴 你会发现他的家里 和你想象的完全不一样~ 你以为他们会时尚.干练.极简 实际上 他们更可能生活在花花绿绿.热闹又复杂的"仓库"里 好多学服装设 ...

  2. 两个网口芯片接一个变压器_一看就会:详细讲解网络变压器作用

    网络变压器具体有T1/E1隔离变压器;ISDN/ADSL接口变压器;VDSL高通/低通滤波器模块.接口变压器;T3/E3.SDH.64KBPS接口变压器;10/100BASE. 1000BASE-TX ...

  3. 去除div最后一个逗号_去除重复值、统计数量,这个公式可以直接套用!

    点击上方蓝字关注星标★不迷路 本文作者:拉登 Dony来源:拉小登(ID:ladengchupin)本文编辑:小叮.竺兰前段时间遇到这样一个问题,让我很头疼. 头疼的原因有 3 点:❶ 问题描述不清晰 ...

  4. idea跳到下一个断点_不看会后悔系列之idea的使用小技巧

    虽然用idea已多达N年,但你对其所有的功能都了如指掌吗?了解如下小tips助你开发更通畅. 调试专题 (1)不用每次都重启debug debug程序时,只修改了一点代码,怎么在不重启程序的前提下,看 ...

  5. python 保存json时最后一个多了一个逗号_从json obj的最后一个对象中删除逗号

    不要用Jinja2手动生成JSON.您不可能希望在所有情况下都生成save和valid JSON.在 在较大的模板中嵌入JSON时,使用^{} built-in filter生成JSON.它不包括尾随 ...

  6. 很多智能手表都用6739芯片_不怕看就怕比:五款智能手表硬件大解析

    驱动之家 在智能硬件这块疆域,智能手表已不算是新物了.三星的智能手表已经做到了第二代,但续航.应用场景.工业设计等方面的不足使得它们一直有话题但 是没大销路.今年moto 360以及Apple Wat ...

  7. java如何给数字每三位加一个逗号_将每三个数字加上逗号处理Java代码

    下面是编程之家 jb51.cc 通过网络收集整理的代码片段. 编程之家小编现在分享给大家,也给大家做个参考. /** * 将每三个数字加上逗号处理(通常使用金额方面的编辑) * * @param st ...

  8. 阿里大牛的Java后端书架来啦,都是Java程序员必看的书籍

    这篇文章推荐的都是我所读过的优秀书籍,部分可能没看完.答应我,一定要看到最后,看完之后应该不会再纠结要看什么书了.走起!!! 这篇文章未涵盖计算机基础比如算法和数据结构.数据库.分布式.微服务方面的书 ...

  9. freemarker 去掉最后一个逗号_从零开始做一个SLG游戏(六)游戏系统以及配置表...

    本文主要是来梳理下游戏内的基本系统(虽然只是照搬polytopia的,但是还是要总结一下),并预先做一些配置表,并实现读取. 一.经济系统 1.总述 经济系统可以是整个游戏的核心.在本游戏中只有一种资 ...

最新文章

  1. 十五个步骤收获学习的习惯
  2. LeetCode 37. Sudoku Solver--数独求解(回溯法)--Java 3ms,Python 80ms 解法
  3. SqlServer 2008 R2定时备份数据库,并且发送邮件通知
  4. 【Linux】一步一步学Linux——date命令(81)
  5. Linux中exit与_exit的区别
  6. 2020年中国住宿业市场网络口碑报告
  7. html遮罩层模态提示,页面遮罩层,并且阻止页面body滚动。bootstrap模态框原理,.bootstrap模态...
  8. CPU多核并发缓存架构介绍
  9. java简易扑克牌_简易扑克牌游戏(java)
  10. ENVI Classic 二次开发简介
  11. 工厂模式的思想主要为
  12. (java+selenium)Web自动化12306模拟人工滑块验证
  13. 【SVM分类】基于布谷鸟算法优化支持向量机SVM实现数据分类附matlab代码
  14. 国产版谷歌地球到底有多牛?看入行20年“老人”怎么回答
  15. CiteSpace中的中介中心性(betweenness)的理解(包含度中心性(degree)、接近中心性(closeness))
  16. 送给孩子的10句人生箴言
  17. 不用u盘如何在小米电视上安装电视直播软件
  18. 计算机DVD驱动禁用怎么恢复,Win7系统禁用或隐藏DVD光驱设备的方法
  19. linux安装/迁移confluence
  20. 利用文件时间批量重命名照片和视频

热门文章

  1. 【sql绕过】Bypass waf notepad of def
  2. ORA-02291: 违反完整约束条件 …… - 未找到父项关键字
  3. list转数组array[]
  4. fourinone分布式协调设计解析
  5. Enterprise Library 系列教程
  6. 弱鸡儿长乐爆零旅Day5
  7. No Thumbnails for Custom Picture Library Definition
  8. malloc在函数内分配内存问题
  9. input标签与图片按钮水平对齐的解决方法
  10. GARFIELD@01-25-2005