InnoDB
支持驻留在 每个表一个文件 表空间中的表的页面级压缩。此功能称为 透明页面压缩。通过使用 CREATE TABLE
或 ALTER TABLE
指定 COMPRESSION
属性来启用页面压缩。支持的压缩算法包括 Zlib
和 LZ4
。
支持的平台
页面压缩需要稀疏文件和打孔支持。页面压缩在使用 NTFS 的 Windows 以及以下 MySQL 支持的 Linux 平台子集(内核级别提供打孔支持)上受支持
RHEL 7 和使用内核版本 3.10.0-123 或更高版本的衍生发行版
OEL 5.10 (UEK2) 内核版本 2.6.39 或更高版本
OEL 6.5 (UEK3) 内核版本 3.8.13 或更高版本
OEL 7.0 内核版本 3.8.13 或更高版本
SLE11 内核版本 3.0-x
SLE12 内核版本 3.12-x
OES11 内核版本 3.0-x
Ubuntu 14.0.4 LTS 内核版本 3.13 或更高版本
Ubuntu 12.0.4 LTS 内核版本 3.2 或更高版本
Debian 7 内核版本 3.2 或更高版本
给定 Linux 发行版的所有可用文件系统可能不支持打孔。
页面压缩的工作原理
写入页面时,将使用指定的压缩算法对其进行压缩。压缩后的数据将写入磁盘,其中打孔机制会从页面末尾释放空块。如果压缩失败,则按原样写出数据。
Linux 上的打孔大小
在 Linux 系统上,文件系统块大小是用于打孔的单位大小。因此,仅当页面数据可以压缩到小于或等于 InnoDB
页面大小减去文件系统块大小时,页面压缩才有效。例如,如果 innodb_page_size=16K
并且文件系统块大小为 4K,则页面数据必须压缩到小于或等于 12K 才能进行打孔。
Windows 上的打孔大小
在 Windows 系统上,稀疏文件的基础架构基于 NTFS 压缩。打孔大小是 NTFS 压缩单元,它是 NTFS 群集大小的 16 倍。群集大小及其压缩单元如下表所示
仅当页面数据可以压缩到小于或等于 InnoDB
页面大小减去压缩单元大小时,Windows 系统上的页面压缩才有效。
默认 NTFS 群集大小为 4KB,其压缩单元大小为 64KB。这意味着页面压缩对开箱即用的 Windows NTFS 配置没有任何好处,因为最大 innodb_page_size
也为 64KB。
要在 Windows 上使用页面压缩,必须使用小于 4K 的群集大小创建文件系统,并且 innodb_page_size
必须至少是压缩单元大小的两倍。例如,要在 Windows 上使用页面压缩,您可以使用 512 字节的群集大小(其压缩单元为 8KB)构建文件系统,并使用 innodb_page_size
值 16K 或更大初始化 InnoDB
。
启用页面压缩
要启用页面压缩,请在 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 TABLE
设置 COMPRESSION=None
。在设置 COMPRESSION=None
后写入表空间将不再使用页面压缩。要解压缩现有页面,您必须在设置 COMPRESSION=None
后使用 OPTIMIZE TABLE
重建表。
ALTER TABLE t1 COMPRESSION="None";
OPTIMIZE TABLE t1;
页面压缩元数据
页面压缩元数据位于信息架构 INNODB_TABLESPACES
表中,位于以下列中:
FS_BLOCK_SIZE
:文件系统块大小,它是用于打孔的单位大小。FILE_SIZE
:文件的表观大小,表示文件的最大大小,未压缩。ALLOCATED_SIZE
:文件的实际大小,即磁盘上分配的空间量。
在类 Unix 系统上,ls -l
显示以字节为单位的表观文件大小(等效于 tablespace_name
.ibdFILE_SIZE
)。要查看磁盘上分配的实际空间量(等效于 ALLOCATED_SIZE
),请使用 du --block-size=1
。tablespace_name
.ibd--block-size=1
选项以字节而不是块为单位打印已分配的空间,以便可以将其与 ls -l
输出进行比较。
使用 SHOW CREATE TABLE
查看当前页面压缩设置(Zlib
、Lz4
或 None
)。一个表可能包含具有不同压缩设置的页面组合。
在以下示例中,从信息架构 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 字节,这是用于打孔的块大小。
识别使用页面压缩的表
要标识启用了页面压缩的表,您可以检查信息架构 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
,则禁用页面压缩。共享表空间中的表不支持页面压缩,这些表包括系统表空间、临时表空间和通用表空间。
撤消日志表空间不支持页面压缩。
重做日志页面不支持页面压缩。
用于空间索引的 R 树页面不压缩。
属于压缩表(
ROW_FORMAT=COMPRESSED
)的页面保持原样。在恢复期间,更新的页面以未压缩的形式写出。
在不支持所用压缩算法的服务器上加载页面压缩的表空间会导致 I/O 错误。
在降级到不支持页面压缩的早期版本的 MySQL 之前,请解压缩使用页面压缩功能的表。要解压缩表,请运行
ALTER TABLE ... COMPRESSION=None
和OPTIMIZE TABLE
。如果 Linux 和 Windows 服务器上都提供了所使用的压缩算法,则可以在它们之间复制页面压缩的表空间。
将页面压缩的表空间文件从一台主机移动到另一台主机时,要保留页面压缩,需要使用保留稀疏文件的实用程序。
与其他平台相比,在使用 NVMFS 的 Fusion-io 硬件上可以实现更好的页面压缩,因为 NVMFS 旨在利用打孔功能。
将页面压缩功能与较大的
InnoDB
页面大小和相对较小的文件系统块大小一起使用可能会导致写入放大。例如,最大InnoDB
页面大小为 64KB,文件系统块大小为 4KB,这可能会提高压缩率,但也可能会增加缓冲池的需求,从而导致 I/O 增加和潜在的写入放大。