美文网首页
MySQL实战宝典 表结构设计篇 06 表压缩:不仅仅是空间压缩

MySQL实战宝典 表结构设计篇 06 表压缩:不仅仅是空间压缩

作者: 逢春枯木 | 来源:发表于2021-06-15 01:08 被阅读0次

    前面几讲,从各种列类型的选择,过渡到表结构的设计,我们已经能够较好的设计出各种业务表,接下来继续学习不同业务表的物理存储设计。很多程序员同学不会在表结构设计之初就考虑存储的设计,只有当业务发展到一定规模才会意识到问题的严重性。而物理存储主要考虑是否要启用表的压缩功能,默认情况下,所有表都是非压缩的。

    但一些同学一听到压缩,总会下意识地认为压缩会导致MySQL数据库地性能下降。这个观点说对也对,所不对也不对,需要根据不同场景进行区分

    表压缩

    数据库中的表是由一行行记录(rows)所组成,每行记录被存储在一个页中,在MySQL中每个页的默认大小为16K,一个个页由组成了每张表的表空间。

    通常我们认为,如果一个页中存放的记录数越多,数据库的性能越高。这是因为数据库表空间中的页是放在磁盘上的,MySQL数据库先要将磁盘中的页读取到内存缓冲池,然后以页为单位来读取和管理记录。

    一个页中存放的记录越多,内存中存放的记录数也就越多,那么存取效率也就越高。若想将一个页中存放的记录数变多,可以启用压缩功能。此外,启用压缩后,存储空间占用也变小了,同样单位的存储能存放的数据也变多了。

    数据库可以根据记录、页、表空间进行压缩,不过实际工程中,普遍使用页压缩技术:

    • 压缩每条记录:因为每次读写都要压缩和解压,过于依赖CPU的计算能力,性能会明显下降;另外单条记录的大小不会太大,压缩效率并不会特别好
    • 压缩表空间:压缩效率非常不错,但要求表空间文件静态不增长,这对于基于磁盘存储的关系型数据库来说很难实现
    • 压缩页:是记录压缩和表空间压缩之间的一中平衡,技能提升压缩效率又能提升读取效率

    压缩需要消耗执行额外的CPU指令,但是压缩并不意味着性能下降,或许反而能额外提升性能,因为大部分的数据库业务系统,CPU的处理能力是过剩的,而I/O负载才是数据库的主要瓶颈。借助页压缩技术,MySQL可以把一个16K的页压缩为8K,甚至4K,这样从磁盘写入或读取时,就能将I/O请求大小减半,甚至更小,从而提升数据库的整体性能。

    压缩是一种平衡,并非一定能提升数据库的性能。这种性能“平衡"取决于压缩解压缩开销带来的收益和压缩解压缩的开销之间的一种平衡。但无论如何,压缩都可以有效整理数据原来的容量,对存储空间来说,压缩的收益是巨大的。

    MySQL压缩表设计

    COMPRESS页压缩

    COMPRESS页压缩是MySQL 5.7版本之前提供的页压缩功能。只要在创建表时指定ROW_FORMAT=COMPRESS并通过选项KEY_BLOCK_SIZE设置压缩的比例。就是将一个页压缩到指定大小。

    需要牢记的是:虽然通过选项ROW_FORMAT启用压缩功能,但这并不是记录级压缩,依然是根据页的维度进行压缩。

    下面是一张日志表:

    CREATE TABLE Log (
        logId BINARY(16) PRIMARY KEY,
        ...
    )
    ROW_FORMAT=COMPRESSED -- 启用COMPRESS页压缩功能
    KEY_BLOCK_SIZE=8; -- 将一个16K的页压缩为8K
    

    如果一个16K的页无法压缩到8K,则会产生2个压缩后的8K页:

    COMPRESS页压缩

    COMPRESS页压缩,适用于一些对性能不敏感的业务表,例如日志表、告警表等,压缩比例通常能达到50%左右。虽然COMPRESS压缩可以有效减小存储空间,但COMPRESS页压缩的实现对性能的开销是巨大的,性能会有明显退化,主要原因是一个压缩页在内存缓存池中存在压缩和解压两个页。

    1个COMPRESS压缩页在内存缓冲池中存在两个版本

    如图所示,Page1和Page2都是压缩页8K,但是在内存中还有其解压后的16K页。这样设计的原因是8K的页用于后续页的更新,16K页用于读取,这样读取就不用每次都做了。

    很明显,这样的实现会增加对内存的开销,会导致缓存池能存放的有效数据变少,MySQL数据库的性能自然出现明显退化。

    TPC压缩

    为了解决COMPRESS页压缩性能下降的问题,从MySQL 5.7版本开始推出了TPC(Transparent Page Compression)压缩功能。其利用文件系统的空洞(Punch Hole)特性进行压缩。可以使用下面的命令创建TPC压缩表:

    CREATE TABLE Transaction (
        taansactionId BINARY(16) PRIMARY KEY,
        ...
    )
    COMPRESSION='ZLIB'; -- 可以选择的有ZLIB压缩算法和LZ4压缩算法,也可以设置为NONE
    

    要使用TPC压缩,首先要确认当前操作系统是否支持空洞特性。通常来说,当前常见的Linux操作系统都已支持空洞特性。Windows系列不支持空洞特性

    由于空洞是文件系统的一个特性,利用空洞压缩只能压缩到文件系统的最小单位4K,且其页压缩是4K对齐的。比如一个16K的页,压缩后为7K,则实际占用空间8K。

    TPC压缩

    一个16K的页压缩后是8K,接着数据库会对16K的页剩余的8K填充0x00,这样当这个16K的页写入到磁盘时,利用文件系统空洞特性,则实际将仅占用8K的物理存储空间。

    空洞压缩的另一个好处是,他对数据库性能的侵入性几乎是无影响的,甚至可能有性能的提升。也是因为TPC不同于COMPRESS页压缩,TPC压缩在内存中只有一个16K的解压缩后的页,对于缓存池没有额外的存储开销。

    另一方面,所有页的读写操作都和非压缩页一样,没有开销,只有当这个页需要刷新到磁盘时,才会触发页压缩功能一次。但由于16K的页被压缩为8K或4K,写入性能会得到一定的提升。

    COMPRESS、TPC对比

    无压缩的测试结果为 13,432 QPS

    传统的 COMPRESS 页压缩性能下降为 10,480 QPS,差不多30%的性能下降。

    基于TPC压缩的测试结果为 18,882,在未压缩的基础上还能有额外 40% 的性能提升。

    表压缩在业务上的使用

    对一些性能不敏感的业务表,例如日志表、告警表等,它们只对存储空间有要求,可以使用COMPRESS页压缩功能。

    在一些较为核心的流水业务表上,推荐使用TPC压缩。因为流水信息是一种非常核心的数据存储业务,通常伴随核心业务。如电商交易,用户扣钱、下单、记流水,这就是一个核心业务的微模型。用户对流水表有性能要求。此外流水又非常大,启用压缩功能可更为有效的存储数据。

    若对压缩产生的性能有所担心,建议:由于流水表通常是按月或天进行存储,对当前正在使用的流水表不要启用TPC压缩,对已经成为历史的流水表启用TPC压缩

    流水表设计

    需要注意的是: 通过命令ALTER TABLE xxx COMPRESSION='ZLIB'可以启用TPC页压缩功能,但是这只对后续新增的数据进行压缩,对原有数据则不进行压缩。如想要对整个表进行压缩,需要执行OPTIMIZE TABLE命令:

    ALTER TABLE Transaction202102 COMPRESSION='ZLIB';
    OPTIMIZE TABLE Transaction202102;
    

    总结

    • MySQL中的压缩都是基于页的压缩;
    • COMPRESS页压缩适用于性能要求不高的业务表;
    • COMPRESS页压缩内存缓冲池存在压缩和解压的两个页,会严重影响性能;
    • 对存储有压缩需求,有希望性能不要有明显退化,推荐使用TPC压缩;
    • 通过 ALTER TABLE 启用 TPC 压缩后,还需要执行命令 OPTIMIZE TABLE 才能立即完成空间的压缩。

    相关文章

      网友评论

          本文标题:MySQL实战宝典 表结构设计篇 06 表压缩:不仅仅是空间压缩

          本文链接:https://www.haomeiwen.com/subject/oqmaeltx.html