InnoDB页面压缩
innoDB支持页面级别的表压缩,这些表位于file-per-table表空间中。这个特性被称为透明页面压缩。通过使用CREATE TABLE或ALTER TABLE指定compression属性,可以启用页面压缩。支持的压缩算法包括Zlib和LZ4。
支持平台
页面压缩需要稀疏文件和穿孔支持。在带有NTFS的Windows上,以及以下支持mysql的Linux平台子集上支持页面压缩,其中内核级别提供了hole punch支持:
. RHEL 7 and derived distributions that use kernel version 3.10.0-123 or higher
. OEL 5.10 (UEK2) kernel version 2.6.39 or higher
. OEL 6.5 (UEK3) kernel version 3.8.13 or higher
. OEL 7.0 kernel version 3.8.13 or higher
. SLE11 kernel version 3.0-x
. SLE12 kernel version 3.12-x
. OES11 kernel version 3.0-x
. Ubuntu 14.0.4 LTS kernel version 3.13 or higher
. Ubuntu 12.0.4 LTS kernel version 3.2 or higher
. Debian 7 kernel version 3.2 or higher
对于给定的Linux发行版,所有可用的文件系统可能都不支持打孔。
页面压缩工作原理
在写入一页时,使用指定的压缩算法对其进行压缩。压缩后的数据被写入磁盘,在磁盘上打孔机制从页的末尾释放空块。如果压缩失败,数据会原样写入。
Linux上的打孔尺寸
在Linux系统中,文件系统块长度是用于打孔的单位长度。因此,只有当页面数据可以压缩到小于或等于InnoDB页面大小减去文件系统块大小时,页面压缩才有效。例如,如果innodb_page_size=16K,文件系统块大小为4K,则页面数据必须压缩到小于或等于12K,才能穿孔。
Windows上的打孔尺寸
在Windows系统上,用于稀疏文件的底层基础设施是基于NTFS压缩。冲孔尺寸为NTFS压缩单元,是NTFS集群尺寸的16倍。集群大小及其压缩单位如下表所示:
Windows NTFS集群大小和压缩单元
集群大小 压缩单元
512 Bytes 8 KB
1 KB 16 KB
2 KB 32 KB
4 KB 64 KB
在Windows系统上,只有当页面数据可以压缩到小于或等于InnoDB页面大小减去压缩单位大小时,页面压缩才有效。
NTFS集群的默认大小是4K,其中压缩单位大小是64K。这意味着页面压缩对于开箱即用的Windows NTFS配置没有任何好处,因为innodb_page_size的最大值也是64K。
为了让页面压缩在Windows上工作,创建文件系统时必须使用小于4K的集群大小,并且innodb_page_size必须至少是压缩单元大小的两倍。例如,为了让页面压缩在Windows上工作,你可以构建一个512字节的集群文件系统(压缩单位是8KB),并将InnoDB初始化为16K或更高的值。
启用页面压缩
要启用页面压缩,请在CREATE TABLE语句中指定compression属性。例如:
mysql> CREATE TABLE t7 (c1 INT) COMPRESSION="zlib"; Query OK, 0 rows affected (0.03 sec) 您还可以在ALTER TABLE语句中启用页面压缩。但是,ALTER TABLE…COMPRESSION只更新表空间的COMPRESSION属性。在设置新的压缩算法之后,对表空间的写入将使用新的设置,但是要将新的压缩算法应用到现有页面,必须使用OPTIMIZE table重建表。
mysql> CREATE TABLE t8 (c1 INT); Query OK, 0 rows affected (0.01 sec) mysql> ALTER TABLE t8 COMPRESSION="zlib"; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> OPTIMIZE TABLE t8; +---------+----------+----------+-------------------------------------------------------------------+ | Table | Op | Msg_type | Msg_text | +---------+----------+----------+-------------------------------------------------------------------+ | undo.t8 | optimize | note | Table does not support optimize, doing recreate + analyze instead | | undo.t8 | optimize | status | OK | +---------+----------+----------+-------------------------------------------------------------------+ 2 rows in set (0.02 sec)
对于Innodb存储引擎不能支持optimize table,Myisam存储引擎支持optimize table。
禁用页面压缩
要禁用页面压缩,请使用ALTER TABLE设置compression =None。在设置COMPRESSION=None后,写入表空间不再使用页面压缩。要解压缩现有页面,必须在设置COMPRESSION=None后使用OPTIMIZE TABLE重新构建表。
mysql> ALTER TABLE t8 COMPRESSION="None"; Query OK, 0 rows affected (0.00 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> OPTIMIZE TABLE t8; +---------+----------+----------+-------------------------------------------------------------------+ | Table | Op | Msg_type | Msg_text | +---------+----------+----------+-------------------------------------------------------------------+ | undo.t8 | optimize | note | Table does not support optimize, doing recreate + analyze instead | | undo.t8 | optimize | status | OK | +---------+----------+----------+-------------------------------------------------------------------+ 2 rows in set (0.02 sec) mysql> show create table t8; +-------+------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +-------+------------------------------------------------------------------------------------------------------------+ | t8 | CREATE TABLE `t8` ( `c1` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMPRESSION='None' | +-------+------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
页面压缩元数据
页面压缩元数据可以在INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES表中找到。在下列列中:
.FS_BLOCK_SIZE:文件系统块大小,打孔时使用的单位大小。
.FILE_SIZE:文件的外观大小,表示未压缩时文件的最大大小。
.ALLOCATED_SIZE:文件的实际大小,即在磁盘上分配的空间量。
在类unix系统上,使用ls -l tablespace_name.ibd以字节为单位给出了明显的文件长度(相当于FILE_SIZE)。要查看磁盘上实际分配的空间大小(相当于ALLOCATED_SIZE),可以使用du –block-size=1 tablespace_name.ibd。–block-size=1选项以字节(而不是块)打印分配的空间,以便与ls -l的输出进行比较。
使用SHOW CREATE TABLE查看当前页面压缩设置(Zlib、Lz4或None)。一个表可能包含具有不同压缩设置的混合页面。
在下面的示例中,从INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES表中检索employees表的页面压缩元数据。
# Create the employees table with Zlib page compression mysql> CREATE TABLE employees ( -> emp_no INT NOT NULL, -> birth_date DATE NOT NULL, -> first_name VARCHAR(14) NOT NULL, -> last_name VARCHAR(16) NOT NULL, -> gender ENUM ('M','F') NOT NULL, -> hire_date DATE NOT NULL, -> PRIMARY KEY (emp_no) -> ) COMPRESSION="zlib"; Query OK, 0 rows affected (0.01 sec) # Insert data mysql> insert into employees values(1,'1985-02-28','yong','jing','M','2023-08-04'); Query OK, 1 row affected (0.00 sec) mysql> commit; Query OK, 0 rows affected (0.00 sec) # Query page compression metadata in INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES mysql> SELECT SPACE, NAME, FS_BLOCK_SIZE, FILE_SIZE, ALLOCATED_SIZE FROM -> INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES WHERE NAME='undo/employees'\G *************************** 1. row *************************** SPACE: 498 NAME: undo/employees FS_BLOCK_SIZE: 4096 FILE_SIZE: 98304 ALLOCATED_SIZE: 61440 1 row in set (0.01 sec)
employees表的页面压缩元数据显示,表面文件大小为98304字节,而实际文件大小(使用页面压缩)为61440字节。文件系统块大小为4096字节,即穿孔时使用的块大小。
页面压缩限制和使用说明
.如果文件系统块大小(或Windows上的压缩单位大小)* 2>innodb_page_size禁用页面压缩。
.对于驻留在共享表空间中的表,包括system表空间、临时表空间和一般表空间,不支持页面压缩。
.undo日志表空间不支持页面压缩。
.重做日志页面不支持页面压缩。
.用于空间索引的R树页面不能被压缩。
.属于压缩表(ROW_FORMAT= compressed)的页面保持原样。
.在恢复过程中,更新后的页面将以未压缩的形式输出。
.在不支持所用压缩算法的服务器上加载页压缩表空间会导致I/O错误。
.在降级到不支持页面压缩的MySQL早期版本之前,请解压使用页面压缩特性的表。要解压一张表,运行ALTER table…compression=None和
optimize table。
.如果所使用的压缩算法在Linux和Windows服务器上可用,则可以在Linux和Windows服务器之间复制页压缩表空间。
.在将页面压缩的表空间文件从一台主机移动到另一台主机时保持页面压缩需要一个保留稀疏文件的实用程序。
.与其他平台相比,使用NVMFS的Fusion-io硬件可以实现更好的页面压缩,因为NVMFS旨在利用打孔功能。
.在InnoDB页面大小较大和文件系统块相对较小的情况下使用页面压缩特性可能会导致写入放大。例如,InnoDB页的最大大小为64KB,而文件系统块的大小为4KB,这可能会提高压缩性能,但也可能会增加对缓冲池的需求,从而导致I/O增加和潜在的写放大。