最近有人问了关于POSTGRESQL 数据压缩的问题,其中有一个问题是关于修改了参数后,无法应用,并且数据库无法启动的问题,我们先从这里说起新的压缩模式。
首先从数据压缩的角度上来说,对于PG 数据库 TOAST 数据存储方式是对于一些大的字段的数据进行压缩和存储的一种模式。默认这样数据压缩的模式是PGLZ的模式。
postgres=# select name,setting,boot_val from pg_settings where name like '%toast%';
-[ RECORD 1 ]-----------------------
name | default_toast_compression
setting | pglz
boot_val | pglz
在数据存入到toast 表文件的时候,会对相关的数据采用压缩的方式进行存储,存储的模式目前在PG16上提供两种选择
1 pglz
2 LZ4
配置可以在系统配置文件中进行配置,如上图进行配置,但配置以后有可能会出现下面的错误,这个错误本身来自于修改参数后,PG无法调用LZ4压缩的组件导致的问题。
postgres@pg16:~$ pg_ctl -D /pgdata/data/ restart
waiting for server to shut down.... done
server stopped
waiting for server to start.... [] 2024-04-09 07:59:31.414 UTC [310971] postmaster 22023 0 LOG: invalid value for parameter "default_toast_compression": "lz4"
[] 2024-04-09 07:59:31.414 UTC [310971] postmaster 22023 0 HINT: Available values: pglz.
[] 2024-04-09 07:59:31.414 UTC [310971] postmaster F0000 0 FATAL: configuration file "/pgdata/data/postgresql.conf" contains errors
stopped waiting
pg_ctl: could not start server
Examine the log output.
postgres@pg16:~$
解决方案,对于数据库层面来说,只能重新编译,先确认 liblz4-dev是否安装了,同时后面需要确认在编译的时候,是否带上 -with-lz4的编译配置选项。
root@pg16:~/postgresql-16.0# sudo apt-get install liblz4-dev
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
liblz4-dev is already the newest version (1.9.3-2build2).
0 upgraded, 0 newly installed, 0 to remove and 112 not upgraded.
root@pg16:~/postgresql-16.0# ./configure --prefix=/usr/local/postgres --bindir=/usr/local/postgres/bin --sysconfdir=/etc --libdir=/usr/local/postgres/libs --includedir=/usr/local/postgres/includes --datadir=/pgdata --datarootdir=/pgdata/root --with-pgport=5432 --with-openssl --with-pam --with-systemd --with-libxml --with-segsize=4 --with-ossp-uuid --with-lz4
操作步骤:
1 停止数据库
2 (非生产数据库) 删除PG可 执行文件目录中的文件
3 重新编译带有 lz4的配置文件,同时在重新编译前需要删除之前已经编译的目录中的文件
4 重新进行应用程序编译
5 启动数据库,并修改参数
Expanded display is on.
postgres=# select * from pg_settings where name like '%toast%';
-[ RECORD 1 ]---+-------------------------------------------------------------
name | default_toast_compression
setting | pglz
unit |
category | Client Connection Defaults / Statement Behavior
short_desc | Sets the default compression method for compressible values.
extra_desc |
context | user
vartype | enum
source | configuration file
min_val |
max_val |
enumvals | {pglz,lz4}
boot_val | pglz
reset_val | pglz
sourcefile | /pgdata/data/postgresql.conf
sourceline | 690
pending_restart | f
postgres=# SET default_toast_compression = lz4;
SET
postgres=# select * from pg_settings where name like '%toast%';
-[ RECORD 1 ]---+-------------------------------------------------------------
name | default_toast_compression
setting | lz4
unit |
category | Client Connection Defaults / Statement Behavior
short_desc | Sets the default compression method for compressible values.
extra_desc |
context | user
vartype | enum
source | session
min_val |
max_val |
enumvals | {pglz,lz4}
boot_val | pglz
reset_val | pglz
sourcefile |
sourceline |
pending_restart | f
然后我们在让系统支持了LZ4 后,我们来进一些测试和实验,来看看两种数据压缩方式的不同。
我们通过下面的示例可以看到,两个表在数据插入之间的区别,一个是使用LZ4 来进行数据压缩处理的,一个是使用PGLZ方式来进行数据处理的。可以看到明显的使用 LZ4 压缩方式的比 PGLZ 方式数据插入的速度快了 2.5倍。
lz4_test=# CREATE TABLE messages (message text compression lz4);
CREATE TABLE
Time: 10.249 ms
lz4_test=# INSERT INTO messages
SELECT (SELECT string_agg(chr(floor(random() * 26)::int + 65), '') FROM generate_series(1,10000))
FROM generate_series(1,10000);
INSERT 0 10000
Time: 1929.160 ms (00:01.929)
lz4_test=#
lz4_test=#
lz4_test=# \c pglz_test
You are now connected to database "pglz_test" as user "postgres".
pglz_test=#
pglz_test=#
pglz_test=# CREATE TABLE messages (message text compression pglz);
ERROR: relation "messages" already exists
Time: 0.709 ms
pglz_test=# INSERT INTO messages
SELECT (SELECT string_agg(chr(floor(random() * 26)::int + 65), '') FROM generate_series(1,10000))
FROM generate_series(1,10000);
INSERT 0 10000
Time: 4889.017 ms (00:04.889)
pglz_test=#
同时我们在启用了 LZ4 后,来查看两个不同压缩方式后的表的大小,可以明显的看出,使用LZ4的表大小是由 119MB 而 使用PGLZ的压缩方式的表的大小为238MB 。
pglz_test=# SELECT
pg_size_pretty(pg_total_relation_size('messages')) AS total_size,
pg_size_pretty(pg_relation_size('messages')) AS table_size,
pg_size_pretty(pg_total_relation_size('messages') - pg_relation_size('messages')) AS index_size;
total_size | table_size | index_size
------------+------------+------------
238 MB | 1024 kB | 237 MB
(1 row)
Time: 1.850 ms
pglz_test=# \c lz4_test
You are now connected to database "lz4_test" as user "postgres".
lz4_test=#
lz4_test=# SELECT
pg_size_pretty(pg_total_relation_size('messages')) AS total_size,
pg_size_pretty(pg_relation_size('messages')) AS table_size,
pg_size_pretty(pg_total_relation_size('messages') - pg_relation_size('messages')) AS index_size;
total_size | table_size | index_size
------------+------------+------------
119 MB | 512 kB | 119 MB
(1 row)
Time: 2.492 ms
另外有同学问如果我将这个表的压缩模式进行修改,那么会发生什么
1 表重新建立
2 表的新的数据插入会使用新的压缩模式来进行数据插入
到底是那个结果我们可以看一下,下面的图,注意表在修改了压缩模式后,filename 是否改变,结果显而易见,还是没有变化,文件也没有重写,并且文件还是原来的大小。
最后我们truncate 表后再次插入数据看是否压缩的模式变化了,下图验证了,的确压缩的模式变化了。
写到最后,在数据库安装时如果你将默认的压缩模式变为LZ4 那么上面的部分你都不用担心,他默认会选择LZ4作为数据压缩的方案,而不是PLGZ,但如果你没有改,那么你就需要在建立表格的时候,来重新对字段进行设置。
本文分享自 AustinDatabases 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!