### 15.9.2 InnoDB 页面压缩

[](<>)[](<>)

`InnoDB`支持对驻留在其中的表进行页级压缩[每表文件](glossary.html#glos_file_per_table)表空间。此功能被称为*透明页面压缩*.通过指定`压缩`属性与[`创建表`](create-table.html)要么[`更改表`](alter-table.html).支持的压缩算法包括`兹库`和`LZ4`.

#### 支持的平台

页面压缩需要稀疏文件和打孔支持。页面压缩在具有 NTFS 的 Windows 以及以下支持 MySQL 的 Linux 平台子集上受支持，其中内核级别提供了打孔支持：

-   使用内核版本 3.10.0-123 或更高版本的 RHEL 7 和派生发行版

-   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`](innodb-parameters.html#sysvar_innodb_page_size)并且文件系统块大小为4K，页面数据必须压缩到小于或等于12K才能打孔。

#### Windows 上的打孔尺寸

在 Windows 系统上，稀疏文件的底层基础结构基于 NTFS 压缩。打孔大小是 NTFS 压缩单元，是 NTFS 簇大小的 16 倍。簇大小及其压缩单位如下表所示：

[](<>)

**表 15.14 Windows NTFS 集群大小和压缩单位**

| 簇的大小 | 压缩单元 |
| ---- | ---- |
| 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`](innodb-parameters.html#sysvar_innodb_page_size)也是64KB。

要在 Windows 上进行页面压缩，必须使用小于 4K 的集群大小创建文件系统，并且[`innodb_page_size`](innodb-parameters.html#sysvar_innodb_page_size)必须至少是压缩单元大小的两倍。例如，要在 Windows 上进行页面压缩，您可以构建集群大小为 512 字节（压缩单元为 8KB）的文件系统并初始化`InnoDB`与[`innodb_page_size`](innodb-parameters.html#sysvar_innodb_page_size)16K 或更大的值。

#### 启用页面压缩

要启用页面压缩，请指定`压缩`中的属性[`创建表`](create-table.html)陈述。例如：

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

您还可以在[`更改表`](alter-table.html)陈述。然而，[`改变表...压缩`](alter-table.html)只更新表空间压缩属性。设置新压缩算法后发生的对表空间的写入使用新设置，但要将新压缩算法应用于现有页面，您必须使用重建表[`优化表`](optimize-table.html).

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

#### 禁用页面压缩

要禁用页面压缩，请设置`压缩=无`使用[`更改表`](alter-table.html).写入设置后发生的表空间`压缩=无`不再使用页面压缩。要解压缩现有页面，您必须使用重建表[`优化表`](optimize-table.html)设置后`压缩=无`.

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

#### 页面压缩元数据

页面压缩元数据位于[`INFORMATION_SCHEMA.INNODB_TABLESPACES`](information-schema-innodb-tablespaces-table.html)表，在以下列中：

-   `FS_BLOCK_SIZE`：文件系统块大小，即打孔时使用的单位大小。

-   `文件大小`：文件的表观大小，表示文件的最大大小，未压缩。

-   `ALLOCATED_SIZE`：文件的实际大小，即磁盘上分配的空间量。

笔记

在类 Unix 系统上，`ls -l *`表空间名称`*.ibd`显示明显的文件大小（相当于`文件大小`) 以字节为单位。查看磁盘上实际分配的空间量（相当于`ALLOCATED_SIZE`）， 采用`杜--块大小=1 *`表空间名称`*.ibd`.这`--块大小=1`选项以字节而不是块打印分配的空间，以便可以将其与`ls -l`输出。

采用[`显示创建表`](show-create-table.html)查看当前页面压缩设置（`兹库`,`Lz4`， 要么`没有`）。一个表可能包含具有不同压缩设置的混合页面。

在下面的示例中，employees 表的页面压缩元数据是从[`INFORMATION_SCHEMA.INNODB_TABLESPACES`](information-schema-innodb-tablespaces-table.html)桌子。

```
# 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
```

employees 表的页面压缩元数据显示表观文件大小为 23068672 字节，而实际文件大小（使用页面压缩）为 19415040 字节。文件系统块大小为 4096 字节，这是用于打孔的块大小。

#### 使用页面压缩识别表

要识别启用了页面压缩的表，您可以查询[`INFORMATION_SCHEMA.TABLES`](information-schema-tables-table.html) `CREATE_OPTIONS`用`压缩`属性：

```
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.html)还显示了`压缩`属性，如果使用。

#### 页面压缩限制和使用说明

-   如果文件系统块大小（或 Windows 上的压缩单元大小），则禁用页面压缩\*2> [`innodb_page_size`](innodb-parameters.html#sysvar_innodb_page_size).

-   位于共享表空间（包括系统表空间、临时表空间和通用表空间）中的表不支持页面压缩。

-   撤消日志表空间不支持页面压缩。

-   重做日志页面不支持页面压缩。

-   用于空间索引的 R 树页面未压缩。

-   属于压缩表的页面（`ROW_FORMAT=压缩`) 保持原样。

-   在恢复期间，更新的页面以未压缩的形式写出。

-   在不支持所用压缩算法的服务器上加载页面压缩表空间会导致 I/O 错误。

-   在降级到不支持页面压缩的早期版本的 MySQL 之前，解压缩使用页面压缩功能的表。要解压缩表，请运行[`ALTER TABLE ...压缩=无`](alter-table.html)和[`优化表`](optimize-table.html).

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

-   在将页压缩表空间文件从一台主机移动到另一台主机时保留页压缩需要保留稀疏文件的实用程序。

-   在具有 NVMFS 的 Fusion-io 硬件上可以实现比在其他平台上更好的页面压缩，因为 NVMFS 旨在利用打孔功能。

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