如果你在生产中运行PostgreSQL,你可能已经注意到,调整检查点对调整服务器和提高数据库整体性能是一件非常有益的事情。然而,这里面还有更多的内容。增加检查点的距离也可以帮助实际减少首先创建的WAL的数量。这是对的。这不仅仅是一个性能问题,而且对创建的日志量也有影响。
Creating a test installation
设置参数
max_wal_size = 128MB
synchronous_commit = off
写入测试数据
% createdb test
% pgbench -s 100 -i test
dropping old tables...
NOTICE: table "pgbench_accounts" does not exist, skipping
NOTICE: table "pgbench_branches" does not exist, skipping
NOTICE: table "pgbench_history" does not exist, skipping
NOTICE: table "pgbench_tellers" does not exist, skipping
creating tables...
generating data...
100000 of 10000000 tuples (1%) done (elapsed 0.13 s, remaining 12.90 s)
200000 of 10000000 tuples (2%) done (elapsed 0.28 s, remaining 13.79 s)
…
9700000 of 10000000 tuples (97%) done (elapsed 12.32 s, remaining 0.38 s)
9800000 of 10000000 tuples (98%) done (elapsed 12.46 s, remaining 0.25 s)
9900000 of 10000000 tuples (99%) done (elapsed 12.59 s, remaining 0.13 s)
10000000 of 10000000 tuples (100%) done (elapsed 12.68 s, remaining 0.00 s)
vacuuming...
creating primary keys...
done.
running a PostgreSQL benchmark
现在让我们运行一个测试。我们想运行10×100万个交易。如果你想在你的数据库上重复测试,确保测试运行的时间足够长。让我们来看看这个测试!
% pgbench -c 10 -j 5 -t 1000000 test
starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 100
query mode: simple
number of clients: 10
number of threads: 5
number of transactions per client: 1000000
number of transactions actually processed: 10000000/10000000
latency average = 0.730 ms
tps = 13699.655677 (including connections establishing)
tps = 13699.737288 (excluding connections establishing)
正如你所看到的,我们成功地运行了大约每秒13.700个交易(在我的个人笔记本电脑上)。让我们来看看创建的WAL的数量。
test=# SELECT pg_current_wal_insert_lsn();
pg_current_wal_insert_lsn
---------------------------
13/522921E8
(1 row)
计算出当前WAL位置的方法是调用pg_current_insert_lsn()函数。对于大多数人来说,这种格式可能是无法理解的,因此将该值转化为可读的数字比较容易。
test=# SELECT pg_size_pretty(pg_current_wal_insert_lsn() - '0/00000000'::pg_lsn);
pg_size_pretty
----------------
77 GB
(1 row)
Increasing checkpoint distances
设置参数
max_wal_size = 150GB
checkpoint_timeout = 1d
synchronous_commit = off
test=# SELECT pg_current_wal_insert_lsn();
pg_current_wal_insert_lsn
---------------------------
1/4F210328
(1 row)test=# SELECT pg_size_pretty(pg_current_wal_insert_lsn() - '0/00000000'::pg_lsn);
pg_size_pretty
----------------
5362 MB
(1 row)
仅仅产生了5.3G的wal
Understanding WAL creation
事务日志的想法是确保在系统崩溃的情况下能够很好地恢复。然而,PostgreSQL不能永远保留交易日志。检查点的目的是确保在WAL从磁盘上删除之前,所有数据在数据文件中是安全的。
技巧来了:如果一个区块在检查点之后第一次被修改,它必须被完全记录下来。整个区块将被写入WAL中。每一个额外的修改都不需要写入整个块–只需要记录修改的内容,当然,这要少得多。
这就是我们在这里看到的主要区别的原因。通过将检查点的距离增加到一个非常高的值,我们基本上将检查点减少到了绝对的最小值,这反过来又减少了 "第一个块 "的写入数量。
从长远来看,改变WAL设置不仅对性能有好处–它还会减少WAL的数量。