热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

PostgreSQL14中TOAST的新压缩算法LZ4,它有多快?

PostgreSQL14提供了

对于列压缩选项,PostgreSQL 14提供了新的压缩方法LZ4。与TOAST中现有的PGLZ压缩方法相比,LZ4压缩更快。本文介绍如何使用整个选项,并和其他压缩算法进行性能比较。

背景

PG中,页是存储数据的单位,默认是8KB。一般情况下,一行数据不允许跨页存储。然而,有一些变长的数据类型,存储的数据可能超出一页大学。为了克服整个限制,大字段域会被压缩或者分割成多个物理行。这个技术就是TOAST:

https://www.postgresql.org/docs/14/storage-toast.html

默认情况下,如果表中有变长列,行数据的大小超过TOAST_TUPLE_THRESHOLD(默认2KB)就会触发TOAST。首先,会先压缩数据;压缩后如果仍然太大,会溢出存储。需要注意,如果列的存储策略指定EXTERNAL/PLAIN,压缩会被禁止

PG14之前版本,TOAST仅支持一个压缩算法PGLZ(PG内置算法)。但是其他压缩算法可能比PGLZ更快或者有更高的压缩率。PG14中有了新压缩选项LZ4压缩,这是一个以速度著称的无损压缩算法。因此我们可以期望它有助于提高TOAST压缩和解压缩的速度。

如何使用LZ4?

为了使用LZ4压缩特性,在编译时需要指定--with-lz4,并且在操作系统中按照LZ4库。通过GUC参数default_toast_compression可以指定PG实例的TOAST默认压缩算法。可以在postgresql.conf中配置,也可以通过SET命令仅改变当前连接:

postgres=# SET default_toast_compression=lz4;
SET

CREATE TABLE创建表时指定列压缩算法:

postgres=# CREATE TABLE tbl (id int,
postgres(#                   col1 text COMPRESSION pglz,
postgres(#                   col2 text COMPRESSION lz4,
postgres(#                   col3 text);
CREATE TABLE
postgres=# \d+ tbl
Table "public.tbl"
Column | Type    | … | Storage  | Compression | …
-------+---------+---+----------+-------------+ …
id     | integer |   | plain    |             |
col1   | text    |   | extended | pglz        |
col2   | text    |   | extended | lz4         |
col3   | text    |   | extended |             |
Access method: heap

我们使用\d+命令可以看到所有列的压缩算法。如果列不支持或者没有指定压缩算法,那么会在Compression列显示空格。上面的例子中,id列不支持压缩算法,col1列使用PGLZ,col2使用LZ4,col3没有指定压缩算法,那么它会使用默认的压缩算法。

可以通过ALTER TABLE修改列压缩算法,但需要注意,修改后的算法仅影响执行整个命令后的insert数据。

postgres=# INSERT INTO tbl VALUES (1, repeat('abc',1000), repeat('abc',1000),repeat('abc',1000));
INSERT 0 1
postgres=# ALTER TABLE tbl ALTER COLUMN col1 SET COMPRESSION lz4;
ALTER TABLE
postgres=# INSERT INTO tbl VALUES (2, repeat('abc',1000), repeat('abc',1000),repeat('abc',1000));
INSERT 0 1
postgres=# SELECT id,
postgres-#        pg_column_compression(id)   AS compression_colid,
postgres-#        pg_column_compression(col1) AS compression_col1,
postgres-#        pg_column_compression(col2) AS compression_col2,
postgres-#        pg_column_compression(col3) AS compression_col3
postgres-# FROM tbl;
id | compression_colid | compression_col1 | compression_col2 | compression_col3
---+-------------------+------------------+------------------+------------------
 1 |                   | pglz             | lz4              | lz4
 2 |                   | lz4              | lz4              | lz4
(2 rows)

可以看到在修改压缩算法前插入的行,col1仍使用PGLZ压缩算法,即使将压缩算法从PGLZ修改到了LZ4。(那么,修改后进行解压时使用哪个算法呢?)

需要注意,如果从其他表扫数据插入本表,例如CREATE TABLE ...AS...或者INSERT INTO...SELECT...,插入的数据使用的压缩算法仍然使用原始数据的压缩方法。pg_dump和pg_dumpall也添加了选项--no-toast-compuression,使用整个选项后,不会dump出TOAST压缩选项。

性能比较

测试了LZ4和PGLZ压缩率和压缩速度。并添加了未压缩数据的测试结果(指定存储策略为EXTERNAL),对于未压缩数据,没有压缩和解压的耗时,但读和写数据的时间会增加。

测试使用的数据:PG documents(一行数据一个HTML文件);SilesiaCorpus提供的数据,包括HTML、Text、源代码、可执行二进制文件、图片:

https://github.com/MiloszKrajewski/SilesiaCorpus

测试机器使用Intel® Xeon® Silver 4210 CPU @2.20GHz with 10 cores/20 threads/2 sockets。

使用pgbench测试SQL语句执行时间,pg_table_size检查表大学(每次执行前都执行VACUUM FULL排除死记录的影响)。

压缩率

PGLZ和LZ4的压缩率都依赖于重复数据,重复的元组越多,压缩率越高。但是如果PG评估这样的压缩率不好时,就不会执行压缩,即使数据大小达到了阈值。因为压缩并没有高效节省磁盘空间,还会带来解压锁的额外时间和资源消耗。

当前PG14中,PGLZ需要至少25%的压缩率,LZ则仅比未压缩数据时小即可。我比较了LZ4、PGLZ的表与未压缩表大小。可以看到,大部分场景下,PGLZ的压缩率稍微好点,压缩率评价为2.23,LZ4的压缩率为2.07。这意味着PGLZ可以节省7%的磁盘空间。

 

Figure 1 - Comparing table sizes (in KB)

压缩/解压缩速度

Insert和查询时TOAST数据会被压缩和解压缩。因此,我执行一些SQL语句查看不同压缩算法带来的影响。

首先比较了INSERT语句,列使用LZ、PGLZ和未使用压缩时的性能。可以看到与未压缩数据比,LZ4耗费稍微多一点时间,PGLZ耗费时间更多。LZ4的压缩时间比PGLZ平均节省20%。这是一项非常显著的改进。

 

Figure 2 - Comparing INSERT performance

下面比较SELECT。与PGLZ相比,LZ4可以节省20%的时间,与未压缩数据相比,没有太大差别。解压缩的消耗已经降到了很低了。

 

Figure 3 - Comparing SELECT performance

再比较16个客户端的INSERT语句并发。与PGLZ相比使用LZ4的单大文件(HTML,英文文本,源代码,二进制执行文件,图片)的压缩性能快60%-70%。插入多个小文件(PG文档),性能提升不大。和未压缩的数据相比,有巨大提升,猜测使用压缩减少了写入磁盘的数据量。

 

Figure 4 - Comparing INSERT performance with 16 clients

 

16个客户端的SELECT,多数场景下,LZ4性能优于PGLZ:

 

Figure 5 - Comparing SELECT performance with 16 clients

 

同样也比较了使用字符串函数的SELECT、UPDATE处理文本的速度。整个场景下LZ4优于PGLZ。LZ4压缩算法的数据与未压缩数据相比,函数处理的速度几乎一样,LZ4算法几乎不会影响字符串操作速度。

 

Figure 6 - Comparing performance using string functions

PGLZ相比,LZ4压缩和解压缩TOAST数据更加高效,并提供很好的性能。和未压缩数据相比,查询速度几乎一样,和PGLZ相比,插入快80%。当然某些场景下压缩率不太好,但如过你想要提升执行速度,强烈推荐使用LZ4算法。

同样需要注意,需要考虑表中的数据是否合适压缩。如果压缩率不好,它仍然会尝试压缩数,然后放弃。这将导致额外的内存资源浪费,并极大影响插入数据的速度。

未来

LZ4对TOAST的压缩和解压缩性能带来了很大提升。除了LZ4,还有很多其他压缩算法比如Zstandard。支持Zstandard用户可以得到比PGLZ更好的压缩率。LZ4 HC具有比LZ4解压98.5%的压缩速度,但是可以大幅提升压缩率。希望未来PG版本可以使用更多的压缩算法。

除了TOAST外,其他场景也需要压缩。据我所知,目前开发版本已经支持WAL的LZ4压缩,这是一项令人兴奋的特性。

原文

https://www.postgresql.fastware.com/blog/what-is-the-new-lz4-toast-compression-in-postgresql-14




推荐阅读
  • MySQL数据库锁机制及其应用(数据库锁的概念)
    本文介绍了MySQL数据库锁机制及其应用。数据库锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,数据是一种供许多用户共享的资源,如何保证数据并发访问的一致性和有效性是数据库必须解决的问题。MySQL的锁机制相对简单,不同的存储引擎支持不同的锁机制,主要包括表级锁、行级锁和页面锁。本文详细介绍了MySQL表级锁的锁模式和特点,以及行级锁和页面锁的特点和应用场景。同时还讨论了锁冲突对数据库并发访问性能的影响。 ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 基于事件驱动的并发编程及其消息通信机制的同步与异步、阻塞与非阻塞、IO模型的分类
    本文介绍了基于事件驱动的并发编程中的消息通信机制,包括同步和异步的概念及其区别,阻塞和非阻塞的状态,以及IO模型的分类。同步阻塞IO、同步非阻塞IO、异步阻塞IO和异步非阻塞IO等不同的IO模型被详细解释。这些概念和模型对于理解并发编程中的消息通信和IO操作具有重要意义。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • 深入理解Java虚拟机的并发编程与性能优化
    本文主要介绍了Java内存模型与线程的相关概念,探讨了并发编程在服务端应用中的重要性。同时,介绍了Java语言和虚拟机提供的工具,帮助开发人员处理并发方面的问题,提高程序的并发能力和性能优化。文章指出,充分利用计算机处理器的能力和协调线程之间的并发操作是提高服务端程序性能的关键。 ... [详细]
  • MySQL语句大全:创建、授权、查询、修改等【MySQL】的使用方法详解
    本文详细介绍了MySQL语句的使用方法,包括创建用户、授权、查询、修改等操作。通过连接MySQL数据库,可以使用命令创建用户,并指定该用户在哪个主机上可以登录。同时,还可以设置用户的登录密码。通过本文,您可以全面了解MySQL语句的使用方法。 ... [详细]
  • 本文介绍了解决Facebook脸书面试题中插入区间的方法,通过模拟遍历的方式判断当前元素与要插入元素的关系,找到插入点并将新区间插入。同时对算法的时间复杂度和空间复杂度进行了分析。 ... [详细]
  • MySQL中的MVVC多版本并发控制机制的应用及实现
    本文介绍了MySQL中MVCC的应用及实现机制。MVCC是一种提高并发性能的技术,通过对事务内读取的内存进行处理,避免写操作堵塞读操作的并发问题。与其他数据库系统的MVCC实现机制不尽相同,MySQL的MVCC是在undolog中实现的。通过undolog可以找回数据的历史版本,提供给用户读取或在回滚时覆盖数据页上的数据。MySQL的大多数事务型存储引擎都实现了MVCC,但各自的实现机制有所不同。 ... [详细]
  • 合并列值-合并为一列问题需求:createtabletab(Aint,Bint,Cint)inserttabselect1,2,3unionallsel ... [详细]
  • MySQL插入数据的四种方式及安全性分析
    本文介绍了MySQL插入数据的四种方式:插入完整的行、插入行的一部分、插入多行和插入查询结果,并对其安全性进行了分析。在插入行时,应注意字段的定义和赋值,以提高安全性。同时指出了使用insert语句的不安全性,应尽量避免使用。建议在表中定义相关字段,并根据定义的字段赋予相应的值,以增加插入操作的安全性。 ... [详细]
author-avatar
mobiledu2502882517
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有