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

两个与性能相关的压缩参数

原创 多米爸比 2022-12-25
1134

翻到一个邮件,介绍与性能相关的参数,除了我们通常设置的shared_buffers,work_mem及hash_mem_multiplier,本文将介绍下面两个与性能相关的压缩参数。

  • default_toast_compression
  • wal_compression

1.default_toast_compression

在PostgreSQL数据库中,page是数据存储的基本单位,page的大小默认为8kB,数据行不允许跨page存储。然而有些数据类型的长度是可变的,数据行有可能超过一个page。为了克服这个限制,大字段值被压缩或分解成多个物理行,这种技术在PostgreSQL里就是“The Oversized-Attribute Storage Technique”,简称为TOAST技术。

从PostgreSQL 14开始,新增了一个default_toast_compression参数,默认值为pglz,可配置的值为pglz和lz4。我们也可以对列进行显式配置,示例如下:

create table tab_compression(
a text compression pglz,
b text compression lz4
);

注意数据库内核只支持pglz算法,使用lz4算法需要编译PostgreSQL时打开–with-lz4选项,否则会出现下面的错误提示。

ERROR:  compression method lz4 not supported
DETAIL:  This functionality requires the server to be built with lz4 support.
HINT:  You need to rebuild PostgreSQL using --with-lz4.

lz4是一种以速度著称的无损压缩算法,可以有效提高压缩和解压的速度,它的压缩性能比pglz更好,且使用更少的CPU。

下面的测试可以看到lz4比pglz性能有几倍的提升:

postgres=# CREATE TABLE tab_compression_2 (
           id int, 
           data text compression pglz
           );
CREATE TABLE

postgres=# insert into tab_compression_2 select i, repeat('x',10000) from generate_series(1,1000000) i;
INSERT 0 1000000
Time: 66568.681 ms (01:06.569)

postgres=# select pg_size_pretty(pg_total_relation_size('tab_compression_2'));
 pg_size_pretty 
----------------
 160 MB
(1 row)

使用pglz压缩,插入一百万条数据用时66秒,空间占用160MB。

清空数据后,修改压缩算法为lz4,插入相同的数据用时7秒,空间占用89MB。

postgres=# truncate table tab_compression_2 ;
TRUNCATE TABLE

postgres=# alter table tab_compression_2 alter column data set compression lz4;
ALTER TABLE

postgres=# insert into tab_compression_2 select i, repeat('x',10000) from generate_series(1,1000000) i;
INSERT 0 1000000
Time: 7677.512 ms (00:07.678)

postgres=# select pg_size_pretty(pg_total_relation_size('tab_compression_2'));
 pg_size_pretty 
----------------
 89 MB
(1 row)

lz4插入相同的数据时间花销比pglz提高接近10倍,空间占用也节省了大约一倍。

数据列的压缩算法在运行过程中可能会被修改,示例如下:

truncate table tab_compression_2 ;
alter table tab_compression_2 alter column data set compression pglz;
insert into tab_compression_2 values(1, repeat('1234567890', 1000));
alter table tab_compression_2 alter column data set compression lz4;
insert into tab_compression_2 values(2, repeat('1234567890', 1000));

我们可以使用新增的pg_column_compression函数来查看数据列的实际压缩算法。

postgres=# select id, pg_column_compression(data) from tab_compression_2;
 id | pg_column_compression 
----+-----------------------
  1 | pglz
  2 | lz4
(2 rows)

当我们使用CREATE TABLE AS或SELECT INSERT复制数据时也可能会存在多种压缩算法,示例如下:

postgres=# create table tab_compression_3 as select * from tab_compression_2;
SELECT 2

postgres=# select id, pg_column_compression(data) from tab_compression_3;
 id | pg_column_compression 
----+-----------------------
  1 | pglz
  2 | lz4
(2 rows)

因此最佳实践是使用全局的参数default_toast_compression来对所有的数据列配置统一的压缩算法,避免使用混合的压缩算法。

2.wal_compression

WAL的全页写(Full Page Write)发生于检查点完成之后的第一次修改中,通过设置wal_compression为on后,PostgreSQL将采用内置的pglz算法压缩全页写再写入WAL。

wal_compression全页写压缩的功能默认是关闭的,如果WAL产生的速度较快,同时还有归档,在比较慢的磁盘上会面临追赶不上WAL生成速度的情形,更复杂的情况是使用了不快的网络。这些场景下开启wal_compression会增大一些CPU负载,但却降低了IO负载,同时也减轻了网络压力。

在PostgreSQL 15里,wal_compression除了设置off和on两个选项,还可以设置pglz、lz4和zstd三个选项值。有基准测试表明,lz4及zstd压缩效率能轻松超越pglz,zstd在某些场景下可以调低默认的压缩级别从而降低CPU的消耗,不过对于通用场景还是推荐使用默认的压缩级别。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论