首页
产品
CLup:PostgreSQL高可用集群平台 CMiner: PostgreSQL中的CDC CData高性能数据库云一体机 CBackup数据库备份恢复云平台 CPDA高性能双子星数据库机 CSYun超融合虚拟机产品 ZQPool数据库连接池 ConshGuard数据保护产品
解决方案
数据库专业技术服务全栈式PostgreSQL解决方案Oracle分布式存储化数据库云PolarDB一体化解决方案
文章
客户及伙伴
中启开源
关于我们
公司简介 联系我们
中启开源

背景

PostgreSQL之前一直被人诟病的地方就是需要使用文件系统缓存,有double buffering的问题,即数据块缓存可能同时存在文件系统缓存中和自己的共享缓存中,形成内存的浪费。

用directio方式可以避免double buffering问题,但由于现有的PostgreSQL数据库代码是在有文件系统缓存的基础上做的开发,如果贸然直接把IO切换成directio,会导致一些场景的性能大大下降,引入一些新的问题,所以社区一直没有实现directio。

最近这几年社区终于行动起来了。社区的思路是在PostgreSQL 16中实现了directio,但是把此特性放在了实验性质里并提醒用户该特性可能导致性能下降,请斟酌使用,在后续的版本(可能是17或之后)会推出高性能的directio功能。

使用方法

PostgreSQL 16增加了数据库参数debug_io_direct,可以取下面三个值的组合:

这三个值对应代码中的三个标志位:

  1. #define IO_DIRECT_DATA 0x01
  2. #define IO_DIRECT_WAL 0x02
  3. #define IO_DIRECT_WAL_INIT 0x04

在postgresql.conf配置此参数:

  1. debug_io_direct='wal,wal_init,data'

然后重启数据库,这时数据库的IO就走directio了。

注意如果使用了directio,我们应该把shared_buffers改大,因为这时没有文件系统缓存了。

由于目前是实验性质,一些大批量的写性能会下降,如我们用pgbench造数据(在一台笔记本电脑上):
使用文件系统缓存时,花费的时间为28秒:

  1. [osdba@dev-rocky9 pgdata]$ pgbench -i -s 100
  2. dropping old tables...
  3. creating tables...
  4. generating data (client-side)...
  5. 2023-11-14 10:18:08.726 CST [12277] LOG: checkpoint starting: wal.91 s))
  6. 2023-11-14 10:18:17.254 CST [12277] LOG: checkpoint complete: wrote 42 buffers (1.0%); 0 WAL file(s) added, 0 removed, 33 recycled; write=8.331 s, sync=0.051 s, total=8.528 s; sync files=30, longest=0.023 s, average=0.002 s; distance=538877 kB, estimate=538877 kB; lsn=0/8CE84CA0, redo lsn=0/6F007570
  7. 10000000 of 10000000 tuples (100%) done (elapsed 17.98 s, remaining 0.00 s)
  8. vacuuming...
  9. creating primary keys...
  10. 2023-11-14 10:18:26.135 CST [12277] LOG: checkpoints are occurring too frequently (18 seconds apart)
  11. 2023-11-14 10:18:26.135 CST [12277] HINT: Consider increasing the configuration parameter "max_wal_size".
  12. 2023-11-14 10:18:26.135 CST [12277] LOG: checkpoint starting: wal
  13. done in 28.16 s (drop tables 0.01 s, create tables 0.02 s, client-side generate 18.15 s, vacuum 0.37 s, primary keys 9.61 s).

使用directio之后时间是63秒:

  1. [osdba@dev-rocky9 pgdata]$ pgbench -i -s 100
  2. dropping old tables...
  3. creating tables...
  4. generating data (client-side)...
  5. 2023-11-14 10:20:22.597 CST [12305] LOG: checkpoint starting: wal16.95 s)
  6. 2023-11-14 10:20:38.596 CST [12305] LOG: checkpoint complete: wrote 36 buffers (0.0%); 0 WAL file(s) added, 0 removed, 33 recycled; write=15.869 s, sync=0.022 s, total=15.999 s; sync files=30,
  7. longest=0.003 s, average=0.001 s; distance=529914 kB, estimate=529914 kB; lsn=0/D920E028, redo lsn=0/BB415128
  8. 10000000 of 10000000 tuples (100%) done (elapsed 34.13 s, remaining 0.00 s)
  9. vacuuming...
  10. creating primary keys...
  11. 2023-11-14 10:21:03.930 CST [12305] LOG: checkpoint starting: wal
  12. done in 62.90 s (drop tables 0.03 s, create tables 0.02 s, client-side generate 34.34 s, vacuum 4.95 s, primary keys 23.56 s).

如果你用命令把文件系统缓存为清理掉,然后再测试:

  1. echo 3 > /proc/sys/vm/drop_caches

有文件缓存的情况:

  1. [osdba@dev-rocky9 pgdata]$ pgbench -T 30 -P 2
  2. pgbench (16.1)
  3. starting vacuum...end.
  4. progress: 2.0 s, 350.5 tps, lat 2.846 ms stddev 0.406, 0 failed
  5. progress: 4.0 s, 368.0 tps, lat 2.714 ms stddev 0.482, 0 failed
  6. progress: 6.0 s, 357.5 tps, lat 2.798 ms stddev 0.546, 0 failed
  7. progress: 8.0 s, 361.5 tps, lat 2.765 ms stddev 0.417, 0 failed
  8. progress: 10.0 s, 311.0 tps, lat 3.214 ms stddev 1.128, 0 failed
  9. progress: 12.0 s, 356.0 tps, lat 2.806 ms stddev 0.630, 0 failed
  10. progress: 14.0 s, 349.0 tps, lat 2.864 ms stddev 0.497, 0 failed
  11. progress: 16.0 s, 346.5 tps, lat 2.885 ms stddev 0.478, 0 failed
  12. ^C

开directio:

  1. [osdba@dev-rocky9 pgdata]$ pgbench -T 30 -P 2
  2. pgbench (16.1)
  3. starting vacuum...end.
  4. progress: 2.0 s, 337.5 tps, lat 2.956 ms stddev 0.366, 0 failed
  5. progress: 4.0 s, 342.0 tps, lat 2.923 ms stddev 0.442, 0 failed
  6. progress: 6.0 s, 348.0 tps, lat 2.870 ms stddev 0.509, 0 failed
  7. progress: 8.0 s, 343.0 tps, lat 2.916 ms stddev 0.665, 0 failed
  8. progress: 10.0 s, 332.5 tps, lat 3.005 ms stddev 0.901, 0 failed
  9. progress: 12.0 s, 341.0 tps, lat 2.933 ms stddev 0.351, 0 failed
  10. progress: 14.0 s, 328.0 tps, lat 3.045 ms stddev 0.954, 0 failed
  11. progress: 16.0 s, 349.0 tps, lat 2.867 ms stddev 0.619, 0 failed
  12. progress: 18.0 s, 347.5 tps, lat 2.876 ms stddev 0.464, 0 failed
  13. progress: 20.0 s, 338.5 tps, lat 2.949 ms stddev 0.727, 0 failed
  14. progress: 22.0 s, 340.5 tps, lat 2.941 ms stddev 0.809, 0 failed
  15. progress: 24.0 s, 329.5 tps, lat 3.032 ms stddev 1.248, 0 failed
  16. progress: 26.0 s, 336.0 tps, lat 2.974 ms stddev 1.116, 0 failed
  17. progress: 28.0 s, 345.5 tps, lat 2.896 ms stddev 0.775, 0 failed
  18. progress: 30.0 s, 353.5 tps, lat 2.827 ms stddev 0.381, 0 failed

会发现两者性能差不多。