原文链接是:https://www.percona.com/blog/2018/12/20/benchmark-postgresql-with-linux-hugepages/
Linux kernel提供了大量可以影响性能的配置参数。关键是针对你的应用程序和负载选择合适配置参数。像其他数据库一样,PostgreSQL 依赖于最优化的Linux kernel。糟糕的配置参数会导致糟糕的性能。因此,重要的是:在每次调整配置参数之后都要对数据库做benchmark,来避免性能降低。在我之前的博文中《Tune Linux Kernel Parameters For PostgreSQL Optimization》 https://www.percona.com/blog/2018/08/29/tune-linux-kernel-parameters-for-postgresql-optimization/ 我描述了一些最有用的Linux kernel配置参数以及这些配置参数如何提高你的数据库性能的。在这篇文章里面,我将会分享打开Linux大页之后,不同的工作负载的benchmark结果。针对不同大小的负载和并发访问客户端,我做了大量的benchmark。
benchmark 机器配置
超微服务器
- CPU: Intel(R) Xeon(R) CPU E5-2683 v3 @ 2.00GHz
2 sockets / 28 cores / 56 threads - 内存: 256GB of RAM
- 存储介质: SAMSUNG SM863 1.9TB Enterprise SSD
- 文件系统: ext4/xfs
操作系统: Ubuntu 16.04.4, kernel 4.13.0-36-generic
PostgreSQL: 11版本
Linux Kernel 配置
我使用了默认的操作系统配置,除了关掉了透明大页(Transparent HugePages)。透明大页是默认打开的,分配页的大小并不可控,对于数据库来说并不太推荐。通常,对于数据库来说,需要固定大小的大页,这个是透明大页所提供不了的。因此,通常推荐的是打开大页,并且要关闭透明大页。
PostgreSQL的配置
我使用了固定的PostgreSQL配置来做benchmark,主要是为了获得不同的负载和不同的配置的大页的测试结果。PostgreSQL配置如下:
shared_buffers = '64GB'
work_mem = '1GB'
random_page_cost = '1'
maintenance_work_mem = '2GB'
synchronous_commit = 'on'
seq_page_cost = '1'
max_wal_size = '100GB'
checkpoint_timeout = '10min'
synchronous_commit = 'on'
checkpoint_completion_target = '0.9'
autovacuum_vacuum_scale_factor = '0.4'
effective_cache_size = '200GB'
min_wal_size = '1GB'
wal_compression = 'ON'
benchmark测试方法
做benchmark的时候,测试的方法是非常重要的。所有的benchmark都会运行三次,每次都会运行30分钟。我取了这三次benchmark的中间值(去掉最低和最高,取中间)。我们使用了PostgreSQL的benchmark工具pgbench来进行测试。pgbench工作时使用了不同的比例因子(scaling fatctor),每个比例因子大概使用16M的内存。
大页 (HugePages)
Linux中大页默认使用的页大小是4K。BSD系统有Super Pages,Windows有Large Pages。PostgreSQL只支持Linux上提供的大页(HugePages).在内存使用率比较高的情况下,大页使用的页面大小太小会降低性能。通过设置大页,可以为应用程序指定内存,就可以降低分配内存和swap的操作开销,所以,可以通过使用大页来提高性能。
下面是使用1G大小的大页的配置。你可以通过从/proc获取这些信息。
cat /proc/meminfo | grep -i huge
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
HugePages_Total: 100
HugePages_Free: 97
HugePages_Rsvd: 63
HugePages_Surp: 0
Hugepagesize: 1048576 kB
对于大页更细节的信息,可以看之前的博客:
https://www.percona.com/blog/2018/08/29/tune-linux-kernel-parameters-for-postgresql-optimization/
通常,大页的大小是从2M到1G,因此(实际生产环境中)合理的配置是使用1G的大小而不是更小的2M页面大小。
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/performance_tuning_guide/s-memory-transhuge
https://kerneltalks.com/services/what-is-huge-pages-in-linux/
benchmark 结果
这个benchmark展示了不同的大页大学的影响。第一组benchmark是使用了Linux默认的4K的页面大小,但是关闭掉了大页。注意,透明大页也关掉了,在下面的其他组的benchmark中也是关闭的。
第二组benchmark使用了2M大小的大页。最终,第三组使用的是1G的大页。
所有的benchmark都是使用了PostgreSQL 11来运行的。这些benchmark的集合实际是不同数据库大小和不同并发客户的组合。下面的图使用TPS来比较性能,Y轴是TPS,X轴是数据库的大小和并发的客户端数量。
很明显,从上图可以看出使用了大页之后,随着数据库的大小的增加、客户端数量的增加,性能也在不断增大,只要数据库的大小在预分配的共享内存(shared buffer)之内。
这幅图也表明TPS随着并发的客户端数量增大而增大,数据库的大小设置为48G的大小。Y轴是TPS, X轴是连接的客户端数量。数据库的大小足够小,能装入到64G的共享内存中。
当把大页设置成1G大小,随着客户端数量的增加,原本已经不错的性能又进一步提升了。
下面这幅图和上面这幅图基本上相同,除了数据库的大小是96G。这就超过了原本64G的共享内存的大小。
一个重要的发现就是:使用1G大页的时候,随着客户端数量的增加,性能最终超过了2M页面大小的情况和标准的4K页面的情况。
测试也表明,随着数据库大小的增加,TPS是逐渐降低的。在这个例子中,客户端的连接数量是32.Y轴是TPS,X轴是数据库大小。
和预期的一样,当数据库的大小超过shared buffer大小时,性能会明显降低。
总结
我首先推荐的一点是我们必须关掉透明大页。当打开大页、并且数据库都能放在共享内存时,你将会看到最大的性能增益。虽然确定大页的大小需要一些尝试和错误,但是设置大页依然可以获得更大的TPS,只要这个大的数据库仍然可以放到shared buffer中。