Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


17.9.2 InnoDB 页面压缩

InnoDB 支持页面级别的压缩,用于在文件-per-表存储空间中的表。这个特性称为透明页面压缩。页面压缩通过在CREATE TABLEALTER TABLE中指定COMPRESSION属性来启用。支持的压缩算法包括ZlibLZ4

支持的平台

页面压缩需要稀疏文件和洞穿支持。页面压缩在 Windows NTFS 和以下子集的 MySQL 支持 Linux 平台上工作,其中 kernel 级别提供洞穿支持:

  • RHEL 7 及其衍生版本,使用 kernel 版本 3.10.0-123 或更高

  • OEL 5.10 (UEK2) kernel 版本 2.6.39 或更高

  • OEL 6.5 (UEK3) kernel 版本 3.8.13 或更高

  • OEL 7.0 kernel 版本 3.8.13 或更高

  • SLE11 kernel 版本 3.0-x

  • SLE12 kernel 版本 3.12-x

  • OES11 kernel 版本 3.0-x

  • Ubuntu 14.0.4 LTS kernel 版本 3.13 或更高

  • Ubuntu 12.0.4 LTS kernel 版本 3.2 或更高

  • Debian 7 kernel 版本 3.2 或更高

Note

Linux 发行版中的所有文件系统可能不支持洞穿。

当页面被写入时,它将使用指定的压缩算法进行压缩。压缩后的数据将被写入磁盘,where the hole punching mechanism 将从页面末尾释放空白块。如果压缩失败,数据将以原样写出。

在 Linux 系统上,文件系统块大小是用于 hole punching 的单位大小。因此,页面压缩只能工作,如果页面数据可以被压缩到小于或等于 InnoDB 页面大小减去文件系统块大小的大小。例如,如果 innodb_page_size=16K,并且文件系统块大小为 4K,页面数据必须压缩到小于或等于 12K,以使 hole punching 可以工作。

在 Windows 系统上,基于 NTFS 压缩的稀疏文件基础结构。hole punching 大小是 NTFS 压缩单元,它是 NTFS 集群大小的 16 倍。集群大小和压缩单元见以下表格:

Table 17.13 Windows NTFS 集群大小和压缩单元

Cluster Size Compression Unit
512 字节 8 KB
1 KB 16 KB
2 KB 32 KB
4 KB 64 KB

Windows 系统上的页面压缩只能工作,如果页面数据可以被压缩到小于或等于 InnoDB 页面大小减去压缩单元大小的大小。

NTFS 集群默认大小为 4KB,压缩单元大小为 64KB。这意味着,对于标准 Windows NTFS 配置,页面压缩没有任何好处,因为最大 innodb_page_size 也为 64KB。

为了在 Windows 上启用页面压缩,文件系统必须使用小于 4K 的 cluster size,并且innodb_ page_size至少要大于压缩单元的两倍。例如,在 Windows 上启用页面压缩,可以将文件系统创建为 cluster size 为 512 字节(压缩单元为 8KB),并初始化InnoDB时设置innodb_ page_size值为 16K 或更大。

要启用页面压缩,请在CREATE TABLE语句中指定COMPRESSION属性。例如:

CREATE TABLE t1 (c1 INT) COMPRESSION="zlib";

您也可以在ALTER TABLE语句中启用页面压缩。然而,ALTER TABLE ... COMPRESSION只更新表空间压缩属性。设置新压缩算法后对表空间的写入将使用新的设置,但是要将新压缩算法应用于现有页面,您必须使用OPTIMIZE TABLE语句重建表。

ALTER TABLE t1 COMPRESSION="zlib";
OPTIMIZE TABLE t1;

要禁用页面压缩,使用ALTER TABLECOMPRESSION=None设置。设置COMPRESSION=None后,写入表空间的操作不再使用页面压缩。要解压现有页面,您必须使用OPTIMIZE TABLE重建表后设置COMPRESSION=None

ALTER TABLE t1 COMPRESSION="None";
OPTIMIZE TABLE t1;

页面压缩元数据可以在信息_schema的INNODB_TABLESPACES表中找到,以下列出几个重要的列:

  • FS_BLOCK_SIZE: 文件系统块大小,这是用于填充洞的单位大小。

  • FILE_SIZE: 文件的明显大小,这表示未压缩文件的最大大小。

  • ALLOCATED_SIZE: 文件的实际大小,这是磁盘上分配的空间量。

Note

在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, Lz4None)。一个表可能包含不同压缩设置的页面。

以下示例中,员工表的页面压缩元数据从信息架构INNODB_TABLESPACES表中检索。

# Create the employees table with Zlib page compression

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";

# Insert data (not shown)

# Query page compression metadata in INFORMATION_SCHEMA.INNODB_TABLESPACES

mysql> SELECT SPACE, NAME, FS_BLOCK_SIZE, FILE_SIZE, ALLOCATED_SIZE FROM
       INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE NAME='employees/employees'\G
*************************** 1. row ***************************
SPACE: 45
NAME: employees/employees
FS_BLOCK_SIZE: 4096
FILE_SIZE: 23068672
ALLOCATED_SIZE: 19415040

员工表的页面压缩元数据显示,文件大小为23068672字节,而实际文件大小(带有页面压缩)为19415040字节。文件系统块大小为4096字节,这是用于填充洞的块大小。

Identifying 表 Using Page Compression

要确定启用了页面压缩的表,可以检查信息架构TABLES表的CREATE_OPTIONS列,用于定义了COMPRESSION属性的表:

mysql> SELECT TABLE_NAME, TABLE_SCHEMA, CREATE_OPTIONS FROM INFORMATION_SCHEMA.TABLES 
       WHERE CREATE_OPTIONS LIKE '%COMPRESSION=%';
+------------+--------------+--------------------+
| TABLE_NAME | TABLE_SCHEMA | CREATE_OPTIONS     |
+------------+--------------+--------------------+
| employees  | test         | COMPRESSION="zlib" |
+------------+--------------+--------------------+

SHOW CREATE TABLE也显示了COMPRESSION属性,如果使用。

  • 如果文件系统块大小(或Windows上的压缩单元大小)* 2>innodb_page_size,则页面压缩被禁用。

  • 页面压缩不支持在共享表空间中存储的表,包括系统表空间、临时表空间和一般表空间。

  • 页面压缩不支持undo日志表空间。

  • 页面压缩不支持redo日志页。

  • R-树页,用于 spatial索引,不会被压缩。

  • 属于压缩表的页(ROW_ FORMAT=COMPRESSED)将保持原样。

  • 在恢复过程中,更新的页将以未压缩的形式写出。

  • 从不支持该压缩算法的服务器上加载一个页面压缩表空间将导致I/O错误。

  • 在降级到不支持页面压缩的早期MySQL版本之前,需要解压使用页面压缩特性的表。要解压一个表,可以运行ALTER TABLE ... COMPRESSION=NoneOPTIMIZE TABLE

  • 页面压缩表空间可以在Linux和Windows服务器之间复制,如果使用的压缩算法在两个服务器上都可用。

  • 将页面压缩表空间文件从一个主机移动到另一个主机时,需要保留稀疏文件的工具以保持页面压缩。

  • 在Fusion-io硬件上使用NVMFS可能会获得更好的页面压缩,因为NVMFS是为了利用punch hole功能而设计的。

  • 使用页面压缩功能与大型InnoDB页面大小和相对较小的文件系统块大小可能会导致写入放大。例如,最大InnoDB页面大小为64KB,文件系统块大小为4KB,虽然可以提高压缩率,但也可能增加缓冲池的需求,从而导致增加I/O和潜在的写入放大。