暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PostgreSQL16中已有实验性质的directio,真正的directio还远吗?

中启乘数 2023-11-20
255

背景

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

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

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

使用方法

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

  • wal_init: 表示建新的wal文件时使用directio
  • wal: 表示读写wal文件时使用directio
  • data: 表示读写数据文件时使用directio

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

#define IO_DIRECT_DATA			0x01
#define IO_DIRECT_WAL 0x02
#define IO_DIRECT_WAL_INIT 0x04

在postgresql.conf配置此参数:

debug_io_direct='wal,wal_init,data'

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

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

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

[osdba@dev-rocky9 pgdata]$ pgbench -i -s 100
dropping old tables...
creating tables...
generating data (client-side)...
2023-11-14 10:18:08.726 CST [12277] LOG: checkpoint starting: wal.91 s))
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
10000000 of 10000000 tuples (100%) done (elapsed 17.98 s, remaining 0.00 s)
vacuuming...
creating primary keys...
2023-11-14 10:18:26.135 CST [12277] LOG: checkpoints are occurring too frequently (18 seconds apart)
2023-11-14 10:18:26.135 CST [12277] HINT: Consider increasing the configuration parameter "max_wal_size".
2023-11-14 10:18:26.135 CST [12277] LOG: checkpoint starting: wal
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秒:

[osdba@dev-rocky9 pgdata]$ pgbench -i -s 100
dropping old tables...
creating tables...
generating data (client-side)...
2023-11-14 10:20:22.597 CST [12305] LOG: checkpoint starting: wal16.95 s)
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,
longest=0.003 s, average=0.001 s; distance=529914 kB, estimate=529914 kB; lsn=0/D920E028, redo lsn=0/BB415128
10000000 of 10000000 tuples (100%) done (elapsed 34.13 s, remaining 0.00 s)
vacuuming...
creating primary keys...
2023-11-14 10:21:03.930 CST [12305] LOG: checkpoint starting: wal
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).

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

echo 3 > proc/sys/vm/drop_caches

有文件缓存的情况:

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

开directio:

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

会发现两者性能差不多。

点击关注乘数科技

扫码添加乘数小助手微信号
邀您进入《PostgreSQL修炼之道:从小工到专家》
读者技术交流群

文章转载自中启乘数,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论