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

PostgreSQL之14.0 lz4 compression

3570

在pg中,行不能跨页存储,为了存储更大的行,pg使用Toast技术将行压缩成更小的块。关于Toast我在之前的文章有介绍过,pg使用固定的页面大小(通常为8kb),并且不允许跨页存储。因此,单行不能直接存储很大的字段值。为了克服这个限制,大字段被压缩或分解成多个物理行。

Toast的压缩采用lz字典压缩算法

源码可见:

https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/common/pg_lzcompress.c

感兴趣的可以看看。

在13.0以前,我们没办法选择如何压缩数据,因为只有一种算法可以压缩PostgreSQL中的数据,那就是pglz。但是14.0版本提供了可配置的lz4 TOAST压缩特性,将会允许我们选用LZ4作为Toast的压缩算法。

commit见:

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=bbe0a81db69bd10bd166907c3701492a29aca294

接下来我们来看一下这个特性。注:接下来演示的内容在centos7系统下操作。

1、下载14.0版本的源码,执行./configure --help | grep LZ4, 可以看到该版本提供了lz4支持,参数是--with-lz4

    ./configure --help | grep LZ4
    --with-lz4 build with LZ4 support
    LZ4_CFLAGS C compiler flags for LZ4, overriding pkg-config
    LZ4_LIBS linker flags for LZ4, overriding pkg-config
    复制

    2、使用--with-lz4参数进行配置。

      sudo ./configure --prefix=/usr/local/postgresql --with-lz4
      复制

      报错:

      configure: error: Package requirements (liblz4) were not met:

      No package 'liblz4' found

      原因是缺少liblz4依赖包。

      3、安装liblz4相关包。

        sudo yum install epel-release
        yum install lz4
        sudo yum install lz4-devel
        复制

        4、编译安装。

          sudo make world ; sudo make install
          复制

          5、添加用户和组。

            sudo useradd postgres
            sudo groupadd postgres
            # 修改postgres用户密码
            sudo passwd postgres
            复制

            6、创建data目录,并修改权限。

              sudo mkdir usr/local/postgresql/data
              sudo chown postgres usr/local/postgresql/data
              sudo chgrp postgres usr/local/postgresql/data
              复制

              7、初始化集群。

                su postgres
                /usr/local/postgresql/bin/initdb -D usr/local/postgresql/data
                复制

                8、启动服务器。

                   usr/local/postgresql/bin/pg_ctl -D usr/local/postgresql/data -l usr/local/postgresql/data/logfile start
                  复制

                  9、登陆。

                    psql -U postgres -h 127.0.01 -p 5432 -d postgres
                    复制

                    10、安装好带有zl4支持的14.0版本后,让我们创建两个表:一个使用默认压缩,另一个使用新的LZ4压缩:

                      create table t1 ( a text );
                      create table t2 ( a text compression LZ4 );

                      复制

                      可以看到t1和t2表的TOAST策略都为extended, 即允许压缩和行外存储。但是t1表的Compression算法是pglz,t2表的compression是lz4。

                      11、接下来,我们分别往两张表中新增一些数据。

                        postgres=# \timing on
                        Timing is on.
                        postgres=# insert into t1(a) select lpad('a',1000000,'a') from generate_series(1,1000);
                        INSERT 0 1000
                        Time: 5488.684 ms (00:05.489)
                        postgres=# insert into t2(a) select lpad('a',1000000,'a') from generate_series(1,1000);
                        INSERT 0 1000
                        Time: 595.999 ms
                        复制

                        可以发现t2插入更快。来看下两张表的toast表。

                          postgres=# select oid,relname from pg_class where oid in (select reltoastrelid from pg_class where relname in ('t1','t2') );
                          oid | relname
                          -------+----------------
                          16397 | pg_toast_16394
                          16402 | pg_toast_16399
                          (2 rows)
                          Time: 0.606 ms
                          postgres=# select pg_size_pretty(pg_relation_size('pg_toast.pg_toast_16394'));
                          pg_size_pretty
                          ----------------
                          12 MB
                          (1 row)

                          Time: 0.349 ms
                          postgres=# select pg_size_pretty(pg_relation_size('pg_toast.pg_toast_16399'));
                          pg_size_pretty
                          ----------------
                          4000 kB
                          (1 row)

                          postgres=# select count(*) from pg_toast.pg_toast_16394;
                          count
                          -------
                          6000
                          (1 row)

                          Time: 0.894 ms
                          postgres=# select count(*) from pg_toast.pg_toast_16399;
                          count
                          -------
                          2000
                          (1 row)

                          Time: 0.463 ms
                          复制

                          可以看到lz4不仅速度更快,而且压缩效果也更好。

                          12、其他用法。

                          查看默认的压缩策略。

                            postgres=# show default_toast_compression ;
                            default_toast_compression
                            ---------------------------
                            pglz
                            (1 row)

                            Time: 0.156 ms
                            复制

                            修改默认压缩策略。

                              postgres=# show default_toast_compression ;
                              default_toast_compression
                              ---------------------------
                              pglz
                              (1 row)

                              Time: 0.156 ms
                              postgres=# SET default_toast_compression TO lz4;
                              SET
                              Time: 0.163 ms
                              postgres=# show default_toast_compression ;
                              default_toast_compression
                              ---------------------------
                              lz4
                              (1 row)

                              Time: 0.163 ms
                              复制

                              修改具体表的某个列的压缩策略。

                                postgres=#  ALTER TABLE t2 ALTER COLUMN a SET COMPRESSION pglz;
                                ALTER TABLE
                                Time: 4.005 ms
                                postgres=# \d+ t2
                                Table "public.t2"
                                Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description
                                --------+------+-----------+----------+---------+----------+-------------+--------------+-------------
                                a | text | | | | extended | pglz | |
                                Access method: heap

                                postgres=#
                                复制

                                其他

                                其实压缩是一个比较宽范的话题,可以从好几个维度去讨论。

                                比如上文我们讲的列压缩技术Toast,也可以是文件系统级别的zfs压缩,以及TimescaleDB里的时间序列数据压缩(可参见:https://docs.timescale.com/timescaledb/latest/how-to-guides/compression/)等等。

                                但是对于所有的压缩,其实就是在节省空间与耗费额外的cpu资源之间做权衡。而存储空间通常又是最便宜的资源......所以说压缩不一定就是有益的,要视情况而定。








                                参考:https://blog.dbi-services.com/postgresql-14-lz4-compression-for-toast/

                                https://www.enterprisedb.com/blog/configurable-lz4-toast-compression

                                https://docs.timescale.com/timescaledb/latest/how-to-guides/compression/

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

                                评论