在MySQL数据库的使用中,对于字段类型设计大家可能都有一些思路和方式,但是针对存储方面的设计,在表结构设计之初可能就没考虑过,只有当业务发展到一定规模才意识到它所带来的问题严重性。而物理存储主要是考虑是否要启用表的压缩功能。默认情况下,所有表都是非压缩的。
一听到压缩,可能会下意识地认为压缩会导致 MySQL 数据库的性能下降。这个观点说对也不对,需要根据不同场景进行区分。 本篇文章,我们就来看一看表的物理存储设计:不同场景下,表压缩功能的使用。
一、表压缩
数据库中的表是由一行行记录(rows)所组成,每行记录被存储在一个页中,在 MySQL 中,一个页的大小默认为 16K,一个个页又组成了每张表的表空间。
如果一个页中存放的记录数越多,数据库的性能越高。这是因为数据库表空间中的页是存放在磁盘上,MySQL 数据库先要将磁盘中的页读取到内存缓冲池,然后以页为单位来读取和管理记录。
那么,一个页中存放的记录越多,内存中能存放的记录数也就越多,那么存取效率也就越高。若想将一个页中存放的记录数变多,可以启用压缩功能。此外,启用压缩后,存储空间占用也变小了,同样单位的存储能存放的数据也变多了。
若要启用压缩技术,数据库可以根据记录、页、表空间进行压缩,不过在实际工程中,我们普遍使用页压缩技术,这是为什么呢?
-
压缩每条记录:每次读写数据都要压缩和解压,对CPU的计算过于依赖,会导致性能明显下降;另外,每条数据的大小一般都不会太大,对于每条数据都进行压缩的话,压缩效率也不是很好。
-
压缩表空间:对表空间的压缩,其实压缩效率还是不错的,但是它要求表空间文件要保持静态,这对关系型数据库来讲又不现实。(不过业务中的历史数据倒是可以考虑)
而基于页的压缩,既能提升压缩效率,又能在性能之间取得一种平衡。
这里大家可能要担心了,启用页压缩的话,性能会有损失,因为压缩需要额外的CPU计算。确实,压缩会给CPU带来一定的消耗。但压缩并不意味着性能下降,有可能还能提升性能呢?因为大部分的数据库业务系统,CPU的处理能力是有余力的,也就是计算时过剩的。IO负载才是数据库的主要瓶颈。
通过页压缩技术,MySQL可以把16K的页压缩到8K或是4K。这样一来,从磁盘读取或写入时,就能将IO请求大小减半。从而提升数据库的整体性能。
二、MySQL压缩表设计
1、COMPRESS 页压缩
COMPRESS 页压缩是 MySQL 5.7 版本之前提供的页压缩功能。只要在创建表时指定ROW_FORMAT=COMPRESS,并设置通过选项 KEY_BLOCK_SIZE 设置压缩的比例。虽然是通过选项 ROW_FORMAT 启用压缩功能,但这并不是记录级压缩,依然是根据页的维度进行压缩。
比如以下示例:我们将一张日志表ROW_FROMAT 设置为 COMPRESS,表示启用 COMPRESS 页压缩功能,KEY_BLOCK_SIZE 设置为 8,表示将一个 16K 的页压缩为 8K。
CREATE TABLE sys_log (
logId BINARY(16) PRIMARY KEY,
......
)
ROW_FORMAT=COMPRESSED
KEY_BLOCK_SIZE=8
COMPRESS 页压缩就是将一个页压缩到指定大小,比如从16K压缩到8K,但是如果无法压缩到8K,则会产生两个8K的页。
COMPRESS 页压缩,适合用于一些对性能不敏感的业务表,例如日志表、监控表、告警表等,压缩比例通常能达到 50% 左右。
虽然 COMPRESS 压缩可以有效减小存储空间,但 COMPRESS 页压缩的实现对性能的开销是巨大的,性能会有明显退化。主要原因是一个压缩页在内存缓冲池中,存在压缩和解压两个页。为了 解决压缩性能下降的问题,从MySQL 5.7 版本开始推出了 TPC 压缩功能。
2、TPC压缩
TPC(Transparent Page Compression)是 5.7 版本推出的一种新的页压缩功能,其利用文件系统的空洞(Punch Hole)特性进行压缩。可以使用下面的命令创建 TPC 压缩表:
CREATE TABLE sys_log (
logid BINARY(16) PRIMARY KEY,
.....
)
COMPRESSION=ZLIB | LZ4 | NONE;
要使用 TPC 压缩,首先要确认当前的操作系统是否支持空洞特性。通常来说,当前常见的 Linux 操作系统都已支持空洞特性。
由于空洞是文件系统的一个特性,利用空洞压缩只能压缩到文件系统的最小单位 4K,且其页压缩是 4K 对齐的。比如一个 16K 的页,压缩后为 7K,则实际占用空间 8K;压缩后为 3K,则实际占用空间是 4K;若压缩后是 13K,则占用空间依然为 16K。
空洞压缩的另一个好处是,它对数据库性能的侵入几乎是无影响的(小于 20%),甚至可能还能有性能的提升。
这是因为不同于 COMPRESS 页压缩,TPC 压缩在内存中只有一个 16K 的解压缩后的页,对于缓冲池没有额外的存储开销。
另一方面,所有页的读写操作都和非压缩页一样,没有开销,只有当这个页需要刷新到磁盘时,才会触发页压缩功能一次。但由于一个 16K 的页被压缩为了 8K 或 4K,其实写入性能会得到一定的提升。
三、总结
对一些对性能不敏感的业务表,例如日志表、监控表、告警表等,它们只对存储空间有要求,因此可以使用 COMPRESS 页压缩功能。
在一些较为核心的业务表上,更推荐使用 TPC压缩。因为核心信息是一种非常重要的数据,通常伴随高频、重要业务。
比如上面提到的订单数据,大部分的电商公司都会对历史订单数据去做单独存储。以确保近期订单数据可以秒查。那么针对这个业务场景,我们可以将历史数据启用TPC压缩功能,对近三个月或六个月的订单数据不启用压缩。
需要特别注意的是: 通过命令 ALTER TABLE xxx COMPRESSION = ZLIB 可以启用 TPC 页压缩功能,但是这只对后续新增的数据会进行压缩,对于原有的数据则不进行压缩。所以上述ALTER TABLE 操作只是修改元数据,瞬间就能完成。
若想要对整个表进行压缩,需要执行 OPTIMIZE TABLE 命令:
ALTER TABLE sys_log COMPRESSION=ZLIB;
OPTIMIZE TABLE sys_log;
文章将持续更新,欢迎关注公众号:服务端技术精选。欢迎点赞、关注、转发。