如何在PostgreSQL13和以下版本中使用lz4压缩文本和二进制数据

从PG14开始,PostgreSQL已经支持LZ4 压缩功能。而PG14之前的版本,其TOAST仅支持一个压缩算法PGLZ(PG内置算法)。众所周知,LZ4比PGLZ的压缩速度快很多。在不要求很高压缩比的场景下,LZ4更适合用于速度敏感型的数据压缩功能。

很多实际场景中,我们为了便于管理,经常将一些大文本和二进制文件存储到数据库里。这时,在不太影响读取速度的时候,存储空间当然是越小越好。很可惜,官方PostgreSQL13和之前的版本不支持LZ4压缩。

那么有没有可能,通过扩展PG的方式来使用lz4压缩功能呢?

答案是可以的。

最近,我就通过开发扩展PG函数的方式实现了lz4压缩和解压缩功能。可以方便的对二进制数据和文本数据进行压缩和解压缩。

我开发了4个自定义函数来进行数据压缩和解压:

# \df
                           List of functions
 Schema |    Name     | Result data type | Argument data types |  Type  
--------+-------------+------------------+---------------------+--------
 public | lz4         | bytea            | bytea bytea         | normal
 public | lz4_utf8    | bytea            | msg text            | normal
 public | un_lz4      | bytea            | bytea bytea         | normal
 public | un_lz4_utf8 | text             | bytea bytea         | normal
(4 rows)
  • lz4:接收bytea类型的数据,返回压缩后的bytea类型数据
  • un_lz4:接收bytea类型的数据,返回解压后的bytea类型数据
  • lz4_utf8:接收utf8编码的文本数据,返回解压后的bytea类型数据
  • un_lz4_utf8:接收bytea类型的数据,返回解压后的utf8编码的文本数据

简单测试一下:

使用lz4压缩

# select lz4('aaaaaaaaaaaaaaaaaaaaaaaaaaaaa,你好,我好,大家好!'::bytea);
                                      lz4                                       
--------------------------------------------------------------------------------
 \x3c0000001f61010009d22ce4bda0e5a5bdefbc8ce688910900c0e5a4a7e5aeb6e5a5bdefbc81
(1 row)

使用un_lz4解压缩,然后convert_from转换成文本

# select convert_from(un_lz4(lz4('aaaaaaaaaaaaaaaaaaaaaaaaaaaaa,你好,我好,大家好!'::bytea)), 'utf8');
                    convert_from                    
----------------------------------------------------
 aaaaaaaaaaaaaaaaaaaaaaaaaaaaa,你好,我好,大家好!
(1 row)

lz4_utf8函数和un_lz4_utf8函数用于在utf8编码环境里,对文本进行lz4压缩和解压缩还原成文本。

以中文绕口令为例。2倍绕口令字节长度:

# select length('八百标兵奔北坡 炮兵并排北边跑 炮兵怕把标兵碰 标兵怕碰炮兵跑;八百标兵奔北坡 炮兵并排北边跑 炮兵怕把标兵碰 标兵怕碰炮兵跑.'::bytea);
 length 
--------
    176
(1 row)

lz4压缩后的字节长度:

# select length(lz4_utf8('八百标兵奔北坡 炮兵并排北边跑 炮兵怕把标兵碰 标兵怕碰炮兵跑;八百标兵奔北坡 炮兵并排北边跑 炮兵怕把标兵碰 标兵怕碰炮兵跑.'));
 length 
--------
     90
(1 row)

压缩并解压缩:

# select un_lz4_utf8(lz4_utf8('八百标兵奔北坡 炮兵并排北边跑 炮兵怕把标兵碰 标兵怕碰炮兵跑;八百标兵奔北坡 炮兵并排北边跑 炮兵怕把标兵碰 标兵怕碰炮兵跑.'));
                                                       un_lz4_utf8                                                        
--------------------------------------------------------------------------------------------------------------------------
 八百标兵奔北坡 炮兵并排北边跑 炮兵怕把标兵碰 标兵怕碰炮兵跑;八百标兵奔北坡 炮兵并排北边跑 炮兵怕把标兵碰 标兵怕碰炮兵跑.
(1 row)

 在数据表格中使用lz4压缩函数。

CREATE TABLE tb_article (
	id serial4 NOT NULL,
	title text NOT NULL,
	content bytea NOT NULL,
	create_time timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
	CONSTRAINT tb_disco_exec_pk PRIMARY KEY (id)
);

插入数据,同时用函数进行内容压缩

# insert into tb_article(title, content) values('哈利波特', lz4_utf8('哈利波特哈利波特哈利波特哈利波特哈利波特哈利波特'));
INSERT 0 1

用 * 查询:

# select * from tb_article;
 id |   title   |                         content                          |          create_time          
----+-----------+----------------------------------------------------------+-------------------------------
  1 | 哈利波特  | \x48000000cfe59388e588a9e6b3a2e789b90c002360e6b3a2e789b9 | 2022-03-21 15:25:45.851421+00
  2 | 哈利波特2 | \x48000000cfe59388e588a9e6b3a2e789b90c002360e6b3a2e789b9 | 2022-03-21 15:25:53.897295+00
(2 rows)

查询并用函数对指定字段进行解压:

# select id, title, un_lz4_utf8(content) as content, create_time from tb_article;
 id |   title   |                     content                      |          create_time          
----+-----------+--------------------------------------------------+-------------------------------
  1 | 哈利波特  | 哈利波特哈利波特哈利波特哈利波特哈利波特哈利波特 | 2022-03-21 15:25:45.851421+00
  2 | 哈利波特2 | 哈利波特哈利波特哈利波特哈利波特哈利波特哈利波特 | 2022-03-21 15:25:53.897295+00
(2 rows)

如何安装扩展函数?

目前扩展函数仅支持Linux操作系统。压缩包里有四个目录:

  • pg10.20
  • pg11.15
  • pg12.10
  • pg13.6

每个目录对应PG的一个大版本。编译时是使用的这些具体版本。但应该可以适用于对应的大版本。

每个目录下有三个文件:

  • pg_lz4--0.1.0.sql
  • pg_lz4.control
  • pg_lz4.so

安装时,将pg_lz4.so拷贝到xxx/postgresql/lib/目录下,pg_lz4.control和pg_lz4--0.1.0.sql文件拷贝到xxx/postgresql/share/extension/目录下。

然后,登录到数据库中创建扩展:

CREATE EXTENSION pg_lz4;

也可以指定创建扩展到具体某个schema下

CREATE EXTENSION IF NOT EXISTS pg_lz4 WITH SCHEMA xxxxxx

然后就可以使用了。

下载链接在这里。

大家使用过程中有任何问题可以找我处理。

当然,如果有对PG扩展开发有需求的,也可以找我聊聊。

我后续会针对PG扩展出更多的文章和函数库。

你可能感兴趣的:(PostgreSQL扩展,PostgreSQL)